@unchainedshop/core-enrollments 1.1.3

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 (46) hide show
  1. package/.npm/package/README +7 -0
  2. package/.npm/package/npm-shrinkwrap.json +205 -0
  3. package/.versions +55 -0
  4. package/README.md +5 -0
  5. package/lib/db/EnrollmentStatus.d.ts +6 -0
  6. package/lib/db/EnrollmentStatus.js +8 -0
  7. package/lib/db/EnrollmentStatus.js.map +1 -0
  8. package/lib/db/EnrollmentsCollection.d.ts +3 -0
  9. package/lib/db/EnrollmentsCollection.js +34 -0
  10. package/lib/db/EnrollmentsCollection.js.map +1 -0
  11. package/lib/db/EnrollmentsSchema.d.ts +2 -0
  12. package/lib/db/EnrollmentsSchema.js +46 -0
  13. package/lib/db/EnrollmentsSchema.js.map +1 -0
  14. package/lib/director/EnrollmentAdapter.d.ts +2 -0
  15. package/lib/director/EnrollmentAdapter.js +67 -0
  16. package/lib/director/EnrollmentAdapter.js.map +1 -0
  17. package/lib/director/EnrollmentDirector.d.ts +2 -0
  18. package/lib/director/EnrollmentDirector.js +46 -0
  19. package/lib/director/EnrollmentDirector.js.map +1 -0
  20. package/lib/director/EnrollmentError.d.ts +6 -0
  21. package/lib/director/EnrollmentError.js +8 -0
  22. package/lib/director/EnrollmentError.js.map +1 -0
  23. package/lib/enrollments-index.d.ts +5 -0
  24. package/lib/enrollments-index.js +6 -0
  25. package/lib/enrollments-index.js.map +1 -0
  26. package/lib/enrollments-settings.d.ts +16 -0
  27. package/lib/enrollments-settings.js +17 -0
  28. package/lib/enrollments-settings.js.map +1 -0
  29. package/lib/module/configureEnrollmentsModule.d.ts +3 -0
  30. package/lib/module/configureEnrollmentsModule.js +323 -0
  31. package/lib/module/configureEnrollmentsModule.js.map +1 -0
  32. package/package.js +37 -0
  33. package/package.json +47 -0
  34. package/plugins/licensed.ts +49 -0
  35. package/src/db/EnrollmentStatus.ts +6 -0
  36. package/src/db/EnrollmentsCollection.ts +38 -0
  37. package/src/db/EnrollmentsSchema.js +53 -0
  38. package/src/director/EnrollmentAdapter.ts +77 -0
  39. package/src/director/EnrollmentDirector.ts +67 -0
  40. package/src/director/EnrollmentError.ts +6 -0
  41. package/src/enrollments-index.ts +8 -0
  42. package/src/enrollments-settings.js +22 -0
  43. package/src/module/configureEnrollmentsModule.ts +502 -0
  44. package/tests/enrollments-index.test.ts +91 -0
  45. package/tsconfig.build.json +26 -0
  46. package/tsconfig.json +8 -0
@@ -0,0 +1,323 @@
1
+ import { emit, registerEvents } from '@unchainedshop/events';
2
+ import { log } from '@unchainedshop/logger';
3
+ import { generateDbFilterById, generateDbMutations, buildSortOptions } from '@unchainedshop/utils';
4
+ import { EnrollmentsCollection } from '../db/EnrollmentsCollection';
5
+ import { EnrollmentsSchema } from '../db/EnrollmentsSchema';
6
+ import { EnrollmentStatus } from '../db/EnrollmentStatus';
7
+ import { EnrollmentDirector } from '../enrollments-index';
8
+ import { enrollmentsSettings } from '../enrollments-settings';
9
+ const ENROLLMENT_EVENTS = [
10
+ 'ENROLLMENT_ADD_PERIOD',
11
+ 'ENROLLMENT_CREATE',
12
+ 'ENROLLMENT_REMOVE',
13
+ 'ENROLLMENT_UPDATE',
14
+ ];
15
+ const buildFindSelector = ({ queryString, status, userId }) => {
16
+ const selector = {
17
+ deleted: null,
18
+ };
19
+ if (status)
20
+ selector.status = { $in: status };
21
+ if (userId)
22
+ selector.userId = userId;
23
+ if (queryString)
24
+ selector.$text = { $search: queryString };
25
+ return selector;
26
+ };
27
+ export const configureEnrollmentsModule = async ({ db, options: enrollmentOptions = {}, }) => {
28
+ registerEvents(ENROLLMENT_EVENTS);
29
+ enrollmentsSettings.configureSettings(enrollmentOptions);
30
+ const Enrollments = await EnrollmentsCollection(db);
31
+ const mutations = generateDbMutations(Enrollments, EnrollmentsSchema);
32
+ const findNewEnrollmentNumber = async (enrollment, index = 0) => {
33
+ const newHashID = enrollmentsSettings.enrollmentNumberHashFn(enrollment, index);
34
+ if ((await Enrollments.countDocuments({ enrollmentNumber: newHashID }, { limit: 1 })) === 0) {
35
+ return newHashID;
36
+ }
37
+ return findNewEnrollmentNumber(enrollment, index + 1);
38
+ };
39
+ const findNextStatus = async (enrollment, requestContext) => {
40
+ let status = enrollment.status;
41
+ const director = await EnrollmentDirector.actions({ enrollment }, requestContext);
42
+ if (status === EnrollmentStatus.INITIAL || status === EnrollmentStatus.PAUSED) {
43
+ if (await director.isValidForActivation()) {
44
+ status = EnrollmentStatus.ACTIVE;
45
+ }
46
+ }
47
+ else if (status === EnrollmentStatus.ACTIVE) {
48
+ if (await director.isOverdue()) {
49
+ status = EnrollmentStatus.PAUSED;
50
+ }
51
+ }
52
+ else if (requestContext.modules.enrollments.isExpired(enrollment, {})) {
53
+ status = EnrollmentStatus.TERMINATED;
54
+ }
55
+ return status;
56
+ };
57
+ const updateStatus = async (enrollmentId, { status, info = '' }, requestContext) => {
58
+ const selector = generateDbFilterById(enrollmentId);
59
+ const enrollment = await Enrollments.findOne(selector, {});
60
+ if (enrollment.status === status)
61
+ return enrollment;
62
+ const date = new Date();
63
+ const modifier = {
64
+ $set: { status, updated: new Date(), updatedBy: requestContext.userId },
65
+ $push: {
66
+ log: {
67
+ date,
68
+ status,
69
+ info,
70
+ },
71
+ },
72
+ };
73
+ switch (status) {
74
+ case EnrollmentStatus.ACTIVE:
75
+ modifier.$set.enrollmentNumber = await findNewEnrollmentNumber(enrollment);
76
+ break;
77
+ case EnrollmentStatus.TERMINATED:
78
+ modifier.$set.expires = enrollment.periods?.pop()?.end || new Date();
79
+ break;
80
+ default:
81
+ break;
82
+ }
83
+ log(`New Status: ${status}`, { enrollmentId });
84
+ await Enrollments.updateOne(selector, modifier);
85
+ const updatedEnrollment = await Enrollments.findOne(selector, {});
86
+ emit('ENROLLMENT_UPDATE', { enrollment, field: 'status' });
87
+ return updatedEnrollment;
88
+ };
89
+ const reactivateEnrollment = async (enrollment) => {
90
+ return enrollment;
91
+ };
92
+ const processEnrollment = async (enrollment, params, requestContext) => {
93
+ let status = await findNextStatus(enrollment, requestContext);
94
+ if (status === EnrollmentStatus.ACTIVE) {
95
+ const nextEnrollment = await reactivateEnrollment(enrollment);
96
+ status = await findNextStatus(nextEnrollment, requestContext);
97
+ }
98
+ return updateStatus(enrollment._id, { status, info: 'enrollment processed' }, requestContext);
99
+ };
100
+ const initializeEnrollment = async (enrollment, params, requestContext) => {
101
+ const { modules, userId } = requestContext;
102
+ // const user = await modules.users.findUserById(enrollment.userId);
103
+ // const locale = modules.users.userLocale(user, requestContext);
104
+ // const reason = "new_enrollment";
105
+ const director = await EnrollmentDirector.actions({ enrollment }, requestContext);
106
+ const period = await director.nextPeriod();
107
+ if (period && (params.orderIdForFirstPeriod || period.isTrial)) {
108
+ const intializedEnrollment = await modules.enrollments.addEnrollmentPeriod(enrollment._id, { ...period, orderId: params.orderIdForFirstPeriod }, userId);
109
+ return processEnrollment(intializedEnrollment, params, requestContext);
110
+ }
111
+ return processEnrollment(enrollment, params, requestContext);
112
+ };
113
+ const sendStatusToCustomer = async (enrollment, params, requestContext) => {
114
+ const { modules, userId } = requestContext;
115
+ let { locale } = params;
116
+ if (!locale) {
117
+ const user = await modules.users.findUserById(enrollment.userId);
118
+ locale = modules.users.userLocale(user, requestContext);
119
+ }
120
+ await modules.worker.addWork({
121
+ type: 'MESSAGE',
122
+ retries: 0,
123
+ input: {
124
+ reason: params.reason || 'status_change',
125
+ locale,
126
+ template: 'ENROLLMENT_STATUS',
127
+ enrollmentId: enrollment._id,
128
+ },
129
+ }, userId);
130
+ return enrollment;
131
+ };
132
+ const updateEnrollmentField = (fieldKey) => async (enrollmentId, fieldValue, userId) => {
133
+ log(`Update enrollment field ${fieldKey.toUpperCase()}`, {
134
+ enrollmentId,
135
+ userId,
136
+ });
137
+ await mutations.update(enrollmentId, { $set: { [fieldKey]: fieldValue } }, userId);
138
+ const enrollment = await Enrollments.findOne(generateDbFilterById(enrollmentId), {});
139
+ emit('ENROLLMENT_UPDATE', { enrollment, field: fieldKey });
140
+ return enrollment;
141
+ };
142
+ return {
143
+ // Queries
144
+ count: async (query) => {
145
+ const enrollmentCount = await Enrollments.countDocuments(buildFindSelector(query));
146
+ return enrollmentCount;
147
+ },
148
+ findEnrollment: async ({ enrollmentId, orderId }, options) => {
149
+ const selector = enrollmentId
150
+ ? generateDbFilterById(enrollmentId)
151
+ : { 'periods.orderId': orderId };
152
+ return Enrollments.findOne(selector, options);
153
+ },
154
+ findEnrollments: async ({ limit, offset, sort, ...query }) => {
155
+ const enrollments = Enrollments.find(buildFindSelector(query), {
156
+ skip: offset,
157
+ limit,
158
+ sort: buildSortOptions(sort),
159
+ });
160
+ return enrollments.toArray();
161
+ },
162
+ // Transformations
163
+ normalizedStatus: (enrollment) => {
164
+ return enrollment.status === null
165
+ ? EnrollmentStatus.INITIAL
166
+ : enrollment.status;
167
+ },
168
+ isExpired: (enrollment, { referenceDate }) => {
169
+ const relevantDate = referenceDate ? new Date(referenceDate) : new Date();
170
+ const expiryDate = new Date(enrollment.expires);
171
+ const isExpired = relevantDate.getTime() > expiryDate.getTime();
172
+ return isExpired;
173
+ },
174
+ // Processing
175
+ terminateEnrollment: async (enrollment, { enrollmentContext }, requestContext) => {
176
+ if (enrollment.status === EnrollmentStatus.TERMINATED)
177
+ return enrollment;
178
+ let updatedEnrollment = await updateStatus(enrollment._id, {
179
+ status: EnrollmentStatus.TERMINATED,
180
+ info: 'terminated manually',
181
+ }, requestContext);
182
+ updatedEnrollment = await processEnrollment(updatedEnrollment, { enrollmentContext }, requestContext);
183
+ return sendStatusToCustomer(updatedEnrollment, {}, requestContext);
184
+ },
185
+ activateEnrollment: async (enrollment, { enrollmentContext }, requestContext) => {
186
+ if (enrollment.status === EnrollmentStatus.TERMINATED)
187
+ return enrollment;
188
+ let updatedEnrollment = await updateStatus(enrollment._id, {
189
+ status: EnrollmentStatus.ACTIVE,
190
+ info: 'activated manually',
191
+ }, requestContext);
192
+ updatedEnrollment = await processEnrollment(updatedEnrollment, { enrollmentContext }, requestContext);
193
+ return sendStatusToCustomer(updatedEnrollment, {}, requestContext);
194
+ },
195
+ // Mutations
196
+ addEnrollmentPeriod: async (enrollmentId, period, userId) => {
197
+ const { start, end, orderId, isTrial } = period;
198
+ const selector = generateDbFilterById(enrollmentId);
199
+ await Enrollments.updateOne(selector, {
200
+ $push: {
201
+ periods: {
202
+ start,
203
+ end,
204
+ orderId,
205
+ isTrial,
206
+ },
207
+ },
208
+ $set: {
209
+ updated: new Date(),
210
+ updatedBy: userId,
211
+ },
212
+ });
213
+ const enrollment = await Enrollments.findOne(selector, {});
214
+ emit('ENROLLMENT_ADD_PERIOD', { enrollment });
215
+ return enrollment;
216
+ },
217
+ create: async ({ countryCode, currencyCode, orderIdForFirstPeriod, ...enrollmentData }, requestContext) => {
218
+ const { userId, services } = requestContext;
219
+ log('Create Enrollment', { userId });
220
+ const currency = currencyCode ||
221
+ (await services.countries.resolveDefaultCurrencyCode({
222
+ isoCode: countryCode,
223
+ }, requestContext));
224
+ const enrollmentId = await mutations.create({
225
+ ...enrollmentData,
226
+ status: EnrollmentStatus.INITIAL,
227
+ periods: [],
228
+ currencyCode: currency,
229
+ countryCode,
230
+ configuration: enrollmentData.configuration || [],
231
+ log: [],
232
+ }, userId);
233
+ const newEnrollment = await Enrollments.findOne(generateDbFilterById(enrollmentId), {});
234
+ const reason = 'new_enrollment';
235
+ const initializedEnrollment = await initializeEnrollment(newEnrollment, {
236
+ orderIdForFirstPeriod,
237
+ reason,
238
+ }, requestContext);
239
+ const enrollment = await sendStatusToCustomer(initializedEnrollment, {
240
+ reason,
241
+ }, requestContext);
242
+ emit('ENROLLMENT_CREATE', { enrollment });
243
+ return enrollment;
244
+ },
245
+ createFromCheckout: async (order, { items, context }, requestContext) => {
246
+ const { modules } = requestContext;
247
+ const orderId = order._id;
248
+ const payment = await modules.orders.payments.findOrderPayment({
249
+ orderPaymentId: order.paymentId,
250
+ });
251
+ const delivery = await modules.orders.deliveries.findDelivery({
252
+ orderDeliveryId: order.deliveryId,
253
+ });
254
+ const template = {
255
+ billingAddress: order.billingAddress,
256
+ contact: order.contact,
257
+ countryCode: order.countryCode,
258
+ currencyCode: order.currency,
259
+ delivery: {
260
+ deliveryProviderId: delivery.deliveryProviderId,
261
+ context: delivery.context,
262
+ },
263
+ orderIdForFirstPeriod: orderId,
264
+ payment: {
265
+ paymentProviderId: payment.paymentProviderId,
266
+ context: payment.context,
267
+ },
268
+ userId: order.userId,
269
+ // TODO: Check with pascal
270
+ meta: order.context,
271
+ ...context,
272
+ };
273
+ const enrollments = await Promise.all(items.map(async (item) => {
274
+ const enrollmentData = await EnrollmentDirector.transformOrderItemToEnrollment(item, template, requestContext);
275
+ return modules.enrollments.create(enrollmentData, requestContext);
276
+ }));
277
+ return enrollments;
278
+ },
279
+ delete: async (enrollmentId, userId) => {
280
+ const deletedCount = await mutations.delete(enrollmentId, userId);
281
+ emit('ORDER_REMOVE', { enrollmentId });
282
+ return deletedCount;
283
+ },
284
+ removeEnrollmentPeriodByOrderId: async (enrollmentId, orderId, userId) => {
285
+ const selector = generateDbFilterById(enrollmentId);
286
+ await Enrollments.updateOne(selector, {
287
+ $set: {
288
+ updated: new Date(),
289
+ updatedBy: userId,
290
+ },
291
+ $pull: {
292
+ periods: { orderId: { $in: [orderId, undefined, null] } },
293
+ },
294
+ });
295
+ return Enrollments.findOne(selector, {});
296
+ },
297
+ updateBillingAddress: updateEnrollmentField('billingAddress'),
298
+ updateContact: updateEnrollmentField('contact'),
299
+ updateContext: updateEnrollmentField('context'),
300
+ updateDelivery: updateEnrollmentField('delivery'),
301
+ updatePayment: updateEnrollmentField('payment'),
302
+ updatePlan: async (enrollmentId, plan, requestContext) => {
303
+ const { userId } = requestContext;
304
+ log(`Update enrollment plan fields`, {
305
+ enrollmentId,
306
+ userId,
307
+ });
308
+ await mutations.update(enrollmentId, {
309
+ productId: plan.productId,
310
+ quantity: plan.quantity,
311
+ configuration: plan.configuration,
312
+ }, userId);
313
+ const selector = generateDbFilterById(enrollmentId);
314
+ const enrollment = await Enrollments.findOne(selector, {});
315
+ emit('ENROLLMENT_UPDATE', { enrollment, field: 'plan' });
316
+ const reason = 'updated_plan';
317
+ const initializedEnrollment = await initializeEnrollment(enrollment, { reason }, requestContext);
318
+ return sendStatusToCustomer(initializedEnrollment, { reason }, requestContext);
319
+ },
320
+ updateStatus,
321
+ };
322
+ };
323
+ //# sourceMappingURL=configureEnrollmentsModule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configureEnrollmentsModule.js","sourceRoot":"","sources":["../../src/module/configureEnrollmentsModule.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACnG,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAE9D,MAAM,iBAAiB,GAAa;IAClC,uBAAuB;IACvB,mBAAmB;IACnB,mBAAmB;IACnB,mBAAmB;CACpB,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAmB,EAAE,EAAE;IAC7E,MAAM,QAAQ,GAKV;QACF,OAAO,EAAE,IAAI;KACd,CAAC;IACF,IAAI,MAAM;QAAE,QAAQ,CAAC,MAAM,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;IAC9C,IAAI,MAAM;QAAE,QAAQ,CAAC,MAAM,GAAG,MAAM,CAAC;IAErC,IAAI,WAAW;QAAE,QAAQ,CAAC,KAAK,GAAG,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;IAE3D,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,0BAA0B,GAAG,KAAK,EAAE,EAC/C,EAAE,EACF,OAAO,EAAE,iBAAiB,GAAG,EAAE,GACS,EAA8B,EAAE;IACxE,cAAc,CAAC,iBAAiB,CAAC,CAAC;IAElC,mBAAmB,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,CAAC;IAEzD,MAAM,WAAW,GAAG,MAAM,qBAAqB,CAAC,EAAE,CAAC,CAAC;IAEpD,MAAM,SAAS,GAAG,mBAAmB,CACnC,WAAW,EACX,iBAAiB,CACa,CAAC;IAEjC,MAAM,uBAAuB,GAAG,KAAK,EAAE,UAAsB,EAAE,KAAK,GAAG,CAAC,EAAmB,EAAE;QAC3F,MAAM,SAAS,GAAG,mBAAmB,CAAC,sBAAsB,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QAChF,IAAI,CAAC,MAAM,WAAW,CAAC,cAAc,CAAC,EAAE,gBAAgB,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE;YAC3F,OAAO,SAAS,CAAC;SAClB;QACD,OAAO,uBAAuB,CAAC,UAAU,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;IACxD,CAAC,CAAC;IAEF,MAAM,cAAc,GAAG,KAAK,EAC1B,UAAsB,EACtB,cAAuB,EACI,EAAE;QAC7B,IAAI,MAAM,GAAG,UAAU,CAAC,MAA0B,CAAC;QACnD,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CAAC,OAAO,CAAC,EAAE,UAAU,EAAE,EAAE,cAAc,CAAC,CAAC;QAElF,IAAI,MAAM,KAAK,gBAAgB,CAAC,OAAO,IAAI,MAAM,KAAK,gBAAgB,CAAC,MAAM,EAAE;YAC7E,IAAI,MAAM,QAAQ,CAAC,oBAAoB,EAAE,EAAE;gBACzC,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC;aAClC;SACF;aAAM,IAAI,MAAM,KAAK,gBAAgB,CAAC,MAAM,EAAE;YAC7C,IAAI,MAAM,QAAQ,CAAC,SAAS,EAAE,EAAE;gBAC9B,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC;aAClC;SACF;aAAM,IAAI,cAAc,CAAC,OAAO,CAAC,WAAW,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,CAAC,EAAE;YACvE,MAAM,GAAG,gBAAgB,CAAC,UAAU,CAAC;SACtC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;IAEF,MAAM,YAAY,GAAsC,KAAK,EAC3D,YAAY,EACZ,EAAE,MAAM,EAAE,IAAI,GAAG,EAAE,EAAE,EACrB,cAAc,EACd,EAAE;QACF,MAAM,QAAQ,GAAG,oBAAoB,CAAC,YAAY,CAAC,CAAC;QACpD,MAAM,UAAU,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAE3D,IAAI,UAAU,CAAC,MAAM,KAAK,MAAM;YAAE,OAAO,UAAU,CAAC;QAEpD,MAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;QACxB,MAAM,QAAQ,GAGV;YACF,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,IAAI,EAAE,EAAE,SAAS,EAAE,cAAc,CAAC,MAAM,EAAE;YACvE,KAAK,EAAE;gBACL,GAAG,EAAE;oBACH,IAAI;oBACJ,MAAM;oBACN,IAAI;iBACL;aACF;SACF,CAAC;QAEF,QAAQ,MAAM,EAAE;YACd,KAAK,gBAAgB,CAAC,MAAM;gBAC1B,QAAQ,CAAC,IAAI,CAAC,gBAAgB,GAAG,MAAM,uBAAuB,CAAC,UAAU,CAAC,CAAC;gBAC3E,MAAM;YACR,KAAK,gBAAgB,CAAC,UAAU;gBAC9B,QAAQ,CAAC,IAAI,CAAC,OAAO,GAAG,UAAU,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC;gBACrE,MAAM;YACR;gBACE,MAAM;SACT;QAED,GAAG,CAAC,eAAe,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,CAAC,CAAC;QAE/C,MAAM,WAAW,CAAC,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAEhD,MAAM,iBAAiB,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAElE,IAAI,CAAC,mBAAmB,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QAE3D,OAAO,iBAAiB,CAAC;IAC3B,CAAC,CAAC;IAEF,MAAM,oBAAoB,GAAG,KAAK,EAAE,UAAsB,EAAE,EAAE;QAC5D,OAAO,UAAU,CAAC;IACpB,CAAC,CAAC;IAEF,MAAM,iBAAiB,GAAG,KAAK,EAC7B,UAAsB,EACtB,MAAmE,EACnE,cAAuB,EACvB,EAAE;QACF,IAAI,MAAM,GAAG,MAAM,cAAc,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;QAE9D,IAAI,MAAM,KAAK,gBAAgB,CAAC,MAAM,EAAE;YACtC,MAAM,cAAc,GAAG,MAAM,oBAAoB,CAAC,UAAU,CAAC,CAAC;YAC9D,MAAM,GAAG,MAAM,cAAc,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC;SAC/D;QAED,OAAO,YAAY,CAAC,UAAU,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,sBAAsB,EAAE,EAAE,cAAc,CAAC,CAAC;IAChG,CAAC,CAAC;IAEF,MAAM,oBAAoB,GAAG,KAAK,EAChC,UAAsB,EACtB,MAA0D,EAC1D,cAAuB,EACvB,EAAE;QACF,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,cAAc,CAAC;QAE3C,oEAAoE;QACpE,iEAAiE;QACjE,mCAAmC;QAEnC,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CAAC,OAAO,CAAC,EAAE,UAAU,EAAE,EAAE,cAAc,CAAC,CAAC;QAClF,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,UAAU,EAAE,CAAC;QAE3C,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,qBAAqB,IAAI,MAAM,CAAC,OAAO,CAAC,EAAE;YAC9D,MAAM,oBAAoB,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,mBAAmB,CACxE,UAAU,CAAC,GAAG,EACd,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,qBAAqB,EAAE,EACpD,MAAM,CACP,CAAC;YAEF,OAAO,iBAAiB,CAAC,oBAAoB,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC;SACxE;QAED,OAAO,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC;IAC/D,CAAC,CAAC;IAEF,MAAM,oBAAoB,GAAG,KAAK,EAChC,UAAsB,EACtB,MAA4C,EAC5C,cAAuB,EACvB,EAAE;QACF,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,cAAc,CAAC;QAE3C,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;QACxB,IAAI,CAAC,MAAM,EAAE;YACX,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YACjE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;SACzD;QAED,MAAM,OAAO,CAAC,MAAM,CAAC,OAAO,CAC1B;YACE,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,CAAC;YACV,KAAK,EAAE;gBACL,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,eAAe;gBACxC,MAAM;gBACN,QAAQ,EAAE,mBAAmB;gBAC7B,YAAY,EAAE,UAAU,CAAC,GAAG;aAC7B;SACF,EACD,MAAM,CACP,CAAC;QAEF,OAAO,UAAU,CAAC;IACpB,CAAC,CAAC;IAEF,MAAM,qBAAqB,GACzB,CAAC,QAAgB,EAAE,EAAE,CAAC,KAAK,EAAE,YAAoB,EAAE,UAAe,EAAE,MAAe,EAAE,EAAE;QACrF,GAAG,CAAC,2BAA2B,QAAQ,CAAC,WAAW,EAAE,EAAE,EAAE;YACvD,YAAY;YACZ,MAAM;SACP,CAAC,CAAC;QAEH,MAAM,SAAS,CAAC,MAAM,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;QAEnF,MAAM,UAAU,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,oBAAoB,CAAC,YAAY,CAAC,EAAE,EAAE,CAAC,CAAC;QAErF,IAAI,CAAC,mBAAmB,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QAE3D,OAAO,UAAU,CAAC;IACpB,CAAC,CAAC;IAEJ,OAAO;QACL,UAAU;QACV,KAAK,EAAE,KAAK,EAAE,KAAsB,EAAE,EAAE;YACtC,MAAM,eAAe,GAAG,MAAM,WAAW,CAAC,cAAc,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC;YACnF,OAAO,eAAe,CAAC;QACzB,CAAC;QAED,cAAc,EAAE,KAAK,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,EAAE;YAC3D,MAAM,QAAQ,GAAG,YAAY;gBAC3B,CAAC,CAAC,oBAAoB,CAAC,YAAY,CAAC;gBACpC,CAAC,CAAC,EAAE,iBAAiB,EAAE,OAAO,EAAE,CAAC;YAEnC,OAAO,WAAW,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAChD,CAAC;QAED,eAAe,EAAE,KAAK,EAAE,EACtB,KAAK,EACL,MAAM,EACN,IAAI,EACJ,GAAG,KAAK,EACwE,EAAE,EAAE;YACpF,MAAM,WAAW,GAAG,WAAW,CAAC,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAAE;gBAC7D,IAAI,EAAE,MAAM;gBACZ,KAAK;gBACL,IAAI,EAAE,gBAAgB,CAAC,IAAI,CAAC;aAC7B,CAAC,CAAC;YAEH,OAAO,WAAW,CAAC,OAAO,EAAE,CAAC;QAC/B,CAAC;QAED,kBAAkB;QAClB,gBAAgB,EAAE,CAAC,UAAU,EAAE,EAAE;YAC/B,OAAO,UAAU,CAAC,MAAM,KAAK,IAAI;gBAC/B,CAAC,CAAC,gBAAgB,CAAC,OAAO;gBAC1B,CAAC,CAAE,UAAU,CAAC,MAA2B,CAAC;QAC9C,CAAC;QAED,SAAS,EAAE,CAAC,UAAU,EAAE,EAAE,aAAa,EAAE,EAAE,EAAE;YAC3C,MAAM,YAAY,GAAG,aAAa,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;YAC1E,MAAM,UAAU,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;YAChD,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,EAAE,GAAG,UAAU,CAAC,OAAO,EAAE,CAAC;YAChE,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,aAAa;QACb,mBAAmB,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,iBAAiB,EAAE,EAAE,cAAc,EAAE,EAAE;YAC/E,IAAI,UAAU,CAAC,MAAM,KAAK,gBAAgB,CAAC,UAAU;gBAAE,OAAO,UAAU,CAAC;YAEzE,IAAI,iBAAiB,GAAG,MAAM,YAAY,CACxC,UAAU,CAAC,GAAG,EACd;gBACE,MAAM,EAAE,gBAAgB,CAAC,UAAU;gBACnC,IAAI,EAAE,qBAAqB;aAC5B,EACD,cAAc,CACf,CAAC;YAEF,iBAAiB,GAAG,MAAM,iBAAiB,CACzC,iBAAiB,EACjB,EAAE,iBAAiB,EAAE,EACrB,cAAc,CACf,CAAC;YAEF,OAAO,oBAAoB,CAAC,iBAAiB,EAAE,EAAE,EAAE,cAAc,CAAC,CAAC;QACrE,CAAC;QAED,kBAAkB,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,iBAAiB,EAAE,EAAE,cAAc,EAAE,EAAE;YAC9E,IAAI,UAAU,CAAC,MAAM,KAAK,gBAAgB,CAAC,UAAU;gBAAE,OAAO,UAAU,CAAC;YAEzE,IAAI,iBAAiB,GAAG,MAAM,YAAY,CACxC,UAAU,CAAC,GAAG,EACd;gBACE,MAAM,EAAE,gBAAgB,CAAC,MAAM;gBAC/B,IAAI,EAAE,oBAAoB;aAC3B,EACD,cAAc,CACf,CAAC;YAEF,iBAAiB,GAAG,MAAM,iBAAiB,CACzC,iBAAiB,EACjB,EAAE,iBAAiB,EAAE,EACrB,cAAc,CACf,CAAC;YAEF,OAAO,oBAAoB,CAAC,iBAAiB,EAAE,EAAE,EAAE,cAAc,CAAC,CAAC;QACrE,CAAC;QAED,YAAY;QACZ,mBAAmB,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;YAC1D,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC;YAChD,MAAM,QAAQ,GAAG,oBAAoB,CAAC,YAAY,CAAC,CAAC;YACpD,MAAM,WAAW,CAAC,SAAS,CAAC,QAAQ,EAAE;gBACpC,KAAK,EAAE;oBACL,OAAO,EAAE;wBACP,KAAK;wBACL,GAAG;wBACH,OAAO;wBACP,OAAO;qBACR;iBACF;gBACD,IAAI,EAAE;oBACJ,OAAO,EAAE,IAAI,IAAI,EAAE;oBACnB,SAAS,EAAE,MAAM;iBAClB;aACF,CAAC,CAAC;YACH,MAAM,UAAU,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YAE3D,IAAI,CAAC,uBAAuB,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;YAE9C,OAAO,UAAU,CAAC;QACpB,CAAC;QAED,MAAM,EAAE,KAAK,EACX,EAAE,WAAW,EAAE,YAAY,EAAE,qBAAqB,EAAE,GAAG,cAAc,EAAE,EACvE,cAAc,EACd,EAAE;YACF,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,cAAc,CAAC;YAE5C,GAAG,CAAC,mBAAmB,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;YAErC,MAAM,QAAQ,GACZ,YAAY;gBACZ,CAAC,MAAM,QAAQ,CAAC,SAAS,CAAC,0BAA0B,CAClD;oBACE,OAAO,EAAE,WAAW;iBACrB,EACD,cAAc,CACf,CAAC,CAAC;YAEL,MAAM,YAAY,GAAG,MAAM,SAAS,CAAC,MAAM,CACzC;gBACE,GAAG,cAAc;gBACjB,MAAM,EAAE,gBAAgB,CAAC,OAAO;gBAChC,OAAO,EAAE,EAAE;gBACX,YAAY,EAAE,QAAQ;gBACtB,WAAW;gBACX,aAAa,EAAE,cAAc,CAAC,aAAa,IAAI,EAAE;gBACjD,GAAG,EAAE,EAAE;aACR,EACD,MAAM,CACP,CAAC;YAEF,MAAM,aAAa,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,oBAAoB,CAAC,YAAY,CAAC,EAAE,EAAE,CAAC,CAAC;YAExF,MAAM,MAAM,GAAG,gBAAgB,CAAC;YAEhC,MAAM,qBAAqB,GAAG,MAAM,oBAAoB,CACtD,aAAa,EACb;gBACE,qBAAqB;gBACrB,MAAM;aACP,EACD,cAAc,CACf,CAAC;YAEF,MAAM,UAAU,GAAG,MAAM,oBAAoB,CAC3C,qBAAqB,EACrB;gBACE,MAAM;aACP,EACD,cAAc,CACf,CAAC;YAEF,IAAI,CAAC,mBAAmB,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;YAE1C,OAAO,UAAU,CAAC;QACpB,CAAC;QAED,kBAAkB,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,cAAc,EAAE,EAAE;YACtE,MAAM,EAAE,OAAO,EAAE,GAAG,cAAc,CAAC;YACnC,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC;YAE1B,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC;gBAC7D,cAAc,EAAE,KAAK,CAAC,SAAS;aAChC,CAAC,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,YAAY,CAAC;gBAC5D,eAAe,EAAE,KAAK,CAAC,UAAU;aAClC,CAAC,CAAC;YAEH,MAAM,QAAQ,GAAG;gBACf,cAAc,EAAE,KAAK,CAAC,cAAc;gBACpC,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,YAAY,EAAE,KAAK,CAAC,QAAQ;gBAC5B,QAAQ,EAAE;oBACR,kBAAkB,EAAE,QAAQ,CAAC,kBAAkB;oBAC/C,OAAO,EAAE,QAAQ,CAAC,OAAO;iBAC1B;gBACD,qBAAqB,EAAE,OAAO;gBAC9B,OAAO,EAAE;oBACP,iBAAiB,EAAE,OAAO,CAAC,iBAAiB;oBAC5C,OAAO,EAAE,OAAO,CAAC,OAAO;iBACzB;gBACD,MAAM,EAAE,KAAK,CAAC,MAAM;gBAEpB,0BAA0B;gBAC1B,IAAI,EAAE,KAAK,CAAC,OAAO;gBAEnB,GAAG,OAAO;aACX,CAAC;YAEF,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,GAAG,CACnC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;gBACvB,MAAM,cAAc,GAAG,MAAM,kBAAkB,CAAC,8BAA8B,CAC5E,IAAI,EACJ,QAAQ,EACR,cAAc,CACf,CAAC;gBAEF,OAAO,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC;YACpE,CAAC,CAAC,CACH,CAAC;YAEF,OAAO,WAAW,CAAC;QACrB,CAAC;QAED,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,EAAE;YACrC,MAAM,YAAY,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;YAClE,IAAI,CAAC,cAAc,EAAE,EAAE,YAAY,EAAE,CAAC,CAAC;YACvC,OAAO,YAAY,CAAC;QACtB,CAAC;QAED,+BAA+B,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE;YACvE,MAAM,QAAQ,GAAG,oBAAoB,CAAC,YAAY,CAAC,CAAC;YACpD,MAAM,WAAW,CAAC,SAAS,CAAC,QAAQ,EAAE;gBACpC,IAAI,EAAE;oBACJ,OAAO,EAAE,IAAI,IAAI,EAAE;oBACnB,SAAS,EAAE,MAAM;iBAClB;gBAED,KAAK,EAAE;oBACL,OAAO,EAAE,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,EAAE;iBAC1D;aACF,CAAC,CAAC;YAEH,OAAO,WAAW,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAC3C,CAAC;QAED,oBAAoB,EAAE,qBAAqB,CAAC,gBAAgB,CAAC;QAC7D,aAAa,EAAE,qBAAqB,CAAC,SAAS,CAAC;QAC/C,aAAa,EAAE,qBAAqB,CAAC,SAAS,CAAC;QAC/C,cAAc,EAAE,qBAAqB,CAAC,UAAU,CAAC;QACjD,aAAa,EAAE,qBAAqB,CAAC,SAAS,CAAC;QAE/C,UAAU,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE;YACvD,MAAM,EAAE,MAAM,EAAE,GAAG,cAAc,CAAC;YAElC,GAAG,CAAC,+BAA+B,EAAE;gBACnC,YAAY;gBACZ,MAAM;aACP,CAAC,CAAC;YAEH,MAAM,SAAS,CAAC,MAAM,CACpB,YAAY,EACZ;gBACE,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,aAAa,EAAE,IAAI,CAAC,aAAa;aAClC,EACD,MAAM,CACP,CAAC;YAEF,MAAM,QAAQ,GAAG,oBAAoB,CAAC,YAAY,CAAC,CAAC;YACpD,MAAM,UAAU,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YAE3D,IAAI,CAAC,mBAAmB,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;YAEzD,MAAM,MAAM,GAAG,cAAc,CAAC;YAC9B,MAAM,qBAAqB,GAAG,MAAM,oBAAoB,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,EAAE,cAAc,CAAC,CAAC;YAEjG,OAAO,oBAAoB,CAAC,qBAAqB,EAAE,EAAE,MAAM,EAAE,EAAE,cAAc,CAAC,CAAC;QACjF,CAAC;QAED,YAAY;KACb,CAAC;AACJ,CAAC,CAAC"}
package/package.js ADDED
@@ -0,0 +1,37 @@
1
+ Package.describe({
2
+ name: 'unchained:core-enrollments',
3
+ version: '1.1.3',
4
+ summary: 'Unchained Engine Core: Enrollments',
5
+ git: 'https://github.com/unchainedshop/unchained',
6
+ documentation: 'README.md',
7
+ });
8
+
9
+ Npm.depends({
10
+ later: '1.2.0',
11
+ locale: '0.1.0',
12
+ moment: '2.29.1',
13
+ 'simpl-schema': '1.12.0',
14
+ '@unchainedshop/logger': '1.1.3',
15
+ '@unchainedshop/utils': '1.1.3',
16
+ // '@unchainedshop/events': '1.1.4', // PEER
17
+ });
18
+
19
+ Package.onUse((api) => {
20
+ api.versionsFrom('2.7.3');
21
+ api.use('ecmascript');
22
+ api.use('typescript');
23
+
24
+ api.mainModule('src/enrollments-index.ts', 'server');
25
+ });
26
+
27
+ Package.onTest((api) => {
28
+ api.use('meteortesting:mocha');
29
+ api.use('ecmascript');
30
+ api.use('typescript');
31
+
32
+ api.use('unchained:mongodb');
33
+ api.use('unchained:core-users');
34
+ api.use('unchained:core-enrollments');
35
+
36
+ api.mainModule('tests/enrollments-index.test.ts');
37
+ });
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@unchainedshop/core-enrollments",
3
+ "version": "1.1.3",
4
+ "main": "lib/enrollments-index.js",
5
+ "types": "lib/enrollments-index.d.ts",
6
+ "type": "module",
7
+ "scripts": {
8
+ "clean": "rm -rf lib",
9
+ "build": "npm run clean && tsc -p tsconfig.build.json",
10
+ "watch": "tsc --watch",
11
+ "link:core": "npm link @unchainedshop/types",
12
+ "test": "cross-env METEOR_PACKAGE_DIRS=../ TEST_CLIENT=0 TEST_WATCH=1 meteor test-packages ./ --driver-package meteortesting:mocha --port 4200"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/unchainedshop/unchained.git"
17
+ },
18
+ "keywords": [
19
+ "unchained",
20
+ "ecommerce",
21
+ "core"
22
+ ],
23
+ "author": "Joël Meiller",
24
+ "license": "EUPL-1.2",
25
+ "bugs": {
26
+ "url": "https://github.com/unchainedshop/unchained/issues"
27
+ },
28
+ "homepage": "https://github.com/unchainedshop/unchained#readme",
29
+ "dependencies": {
30
+ "@unchainedshop/events": "latest",
31
+ "@unchainedshop/logger": "latest",
32
+ "@unchainedshop/utils": "latest",
33
+ "later": "1.2.0",
34
+ "locale": "0.1.0",
35
+ "moment": "^2.29.3",
36
+ "simpl-schema": "^1.12.2"
37
+ },
38
+ "devDependencies": {
39
+ "@types/chai": "^4.3.1",
40
+ "@types/locale": "^0.1.1",
41
+ "@types/mocha": "^9.1.1",
42
+ "@unchainedshop/types": "latest",
43
+ "chai": "^4.3.6",
44
+ "cross-env": "^7.0.3",
45
+ "typescript": "^4.7.4"
46
+ }
47
+ }
@@ -0,0 +1,49 @@
1
+ import { IEnrollmentAdapter } from '@unchainedshop/types/enrollments';
2
+ import { EnrollmentDirector, EnrollmentAdapter } from 'meteor/unchained:core-enrollments';
3
+
4
+ const rangeMatcher = (date = new Date()) => {
5
+ const timestamp = date.getTime();
6
+ return ({ start, end }) => {
7
+ const startTimestamp = new Date(start).getTime();
8
+ const endTimestamp = new Date(end).getTime();
9
+ return startTimestamp <= timestamp && endTimestamp >= timestamp;
10
+ };
11
+ };
12
+
13
+ const LicensedEnrollments: IEnrollmentAdapter = {
14
+ ...EnrollmentAdapter,
15
+
16
+ key: 'shop.unchained.enrollments.licensed',
17
+ version: '1.0',
18
+ label: 'Simple Licensed Enrollments',
19
+
20
+ isActivatedFor: (productPlan) => {
21
+ return productPlan?.usageCalculationType === 'LICENSED';
22
+ },
23
+
24
+ actions: (params) => {
25
+ return {
26
+ ...EnrollmentAdapter.actions(params),
27
+
28
+ isValidForActivation: async () => {
29
+ const periods = params.enrollment?.periods || [];
30
+ return periods.findIndex(rangeMatcher()) !== -1;
31
+ },
32
+
33
+ isOverdue: async () => {
34
+ return false;
35
+ },
36
+
37
+ configurationForOrder: async (context) => {
38
+ const { period } = context;
39
+ const beginningOfPeriod = period.start.getTime() <= new Date().getTime();
40
+ if (beginningOfPeriod) {
41
+ return context;
42
+ }
43
+ return null;
44
+ },
45
+ };
46
+ },
47
+ };
48
+
49
+ EnrollmentDirector.registerAdapter(LicensedEnrollments);
@@ -0,0 +1,6 @@
1
+ export enum EnrollmentStatus {
2
+ INITIAL = 'INITIAL',
3
+ ACTIVE = 'ACTIVE',
4
+ PAUSED = 'PAUSED',
5
+ TERMINATED = 'TERMINATED',
6
+ }
@@ -0,0 +1,38 @@
1
+ import { Db } from '@unchainedshop/types/common';
2
+ import { buildDbIndexes } from '@unchainedshop/utils';
3
+ import { Enrollment } from '@unchainedshop/types/enrollments';
4
+
5
+ export const EnrollmentsCollection = async (db: Db) => {
6
+ const Enrollments = db.collection<Enrollment>('enrollments');
7
+
8
+ // Enrollment Indexes
9
+ await buildDbIndexes<Enrollment>(Enrollments, [
10
+ { index: { userId: 1 } },
11
+ { index: { productId: 1 } },
12
+ { index: { status: 1 } },
13
+ { index: { enrollmentNumber: 1 } },
14
+ {
15
+ index: {
16
+ _id: 'text',
17
+ userId: 'text',
18
+ enrollmentNumber: 'text',
19
+ status: 'text',
20
+ 'contact.telNumber': 'text',
21
+ 'contact.emailAddress': 'text',
22
+ },
23
+ options: {
24
+ weights: {
25
+ _id: 8,
26
+ userId: 3,
27
+ enrollmentNumber: 6,
28
+ 'contact.telNumber': 5,
29
+ 'contact.emailAddress': 4,
30
+ status: 1,
31
+ },
32
+ name: 'enrollment_fulltext_search',
33
+ },
34
+ },
35
+ ]);
36
+
37
+ return Enrollments;
38
+ };
@@ -0,0 +1,53 @@
1
+ import { Schemas } from '@unchainedshop/utils';
2
+ import SimpleSchema from 'simpl-schema';
3
+
4
+ export const PeriodSchema = new SimpleSchema(
5
+ {
6
+ orderId: { type: String },
7
+ start: { type: Date, required: true },
8
+ end: { type: Date, required: true },
9
+ isTrial: { type: Boolean },
10
+ },
11
+ {
12
+ requiredByDefault: false,
13
+ },
14
+ );
15
+
16
+ export const EnrollmentsSchema = new SimpleSchema(
17
+ {
18
+ userId: { type: String, required: true },
19
+ status: { type: String, required: true },
20
+ productId: { type: String, required: true },
21
+ quantity: { type: Number },
22
+ configuration: Array,
23
+ 'configuration.$': {
24
+ type: Object,
25
+ required: true,
26
+ },
27
+ 'configuration.$.key': {
28
+ type: String,
29
+ required: true,
30
+ },
31
+ 'configuration.$.value': {
32
+ type: String,
33
+ },
34
+ enrollmentNumber: String,
35
+ expires: Date,
36
+ meta: { type: Object, blackbox: true },
37
+ billingAddress: Schemas.Address,
38
+ contact: Schemas.Contact,
39
+ currencyCode: String,
40
+ countryCode: String,
41
+ payment: { type: Object },
42
+ 'payment.paymentProviderId': String,
43
+ 'payment.context': Schemas.contextFields.context,
44
+ delivery: { type: Object },
45
+ 'delivery.deliveryProviderId': String,
46
+ 'delivery.context': Schemas.contextFields.context,
47
+ periods: { type: Array },
48
+ 'periods.$': { type: PeriodSchema, required: true },
49
+ ...Schemas.logFields,
50
+ ...Schemas.timestampFields,
51
+ },
52
+ { requiredByDefault: false },
53
+ );
@@ -0,0 +1,77 @@
1
+ import { log, LogLevel } from '@unchainedshop/logger';
2
+ import moment from 'moment';
3
+
4
+ import { IEnrollmentAdapter } from '@unchainedshop/types/enrollments';
5
+
6
+ const periodForReferenceDate = (referenceDate: Date, intervalCount = 1, interval = 'WEEK') => {
7
+ const start = moment(referenceDate).startOf(interval === 'HOUR' ? 'minute' : 'hour');
8
+ return {
9
+ start: start.toDate(),
10
+ end: start.clone().add(intervalCount, interval).toDate(),
11
+ };
12
+ };
13
+
14
+ export const EnrollmentAdapter: Omit<IEnrollmentAdapter, 'key' | 'label' | 'version'> = {
15
+ isActivatedFor: () => {
16
+ return false;
17
+ },
18
+
19
+ transformOrderItemToEnrollmentPlan: async (item) => {
20
+ return {
21
+ configuration: item.configuration,
22
+ productId: item.productId,
23
+ quantity: item.quantity,
24
+ };
25
+ },
26
+
27
+ actions: (context) => {
28
+ return {
29
+ configurationForOrder: async () => {
30
+ throw new Error(`Not implemented on EnrollmentAdapter`);
31
+ },
32
+
33
+ isOverdue: async () => false,
34
+ isValidForActivation: async () => false,
35
+
36
+ nextPeriod: async () => {
37
+ const { enrollment } = context;
38
+ const product = await context.modules.products.findProduct({
39
+ productId: enrollment.productId,
40
+ });
41
+ const plan = product?.plan;
42
+ const referenceDate = new Date();
43
+ if (!plan) return null;
44
+
45
+ if (plan.trialIntervalCount && !enrollment?.periods?.length) {
46
+ return {
47
+ ...periodForReferenceDate(referenceDate, plan.trialIntervalCount, plan.trialInterval),
48
+ isTrial: true,
49
+ };
50
+ }
51
+
52
+ const lastEnd = enrollment?.periods?.reduce((acc, item) => {
53
+ if (!acc) return item.end;
54
+ const endDate = new Date(item.end);
55
+ if (acc.getTime() < endDate.getTime()) {
56
+ return endDate;
57
+ }
58
+ return acc;
59
+ }, referenceDate);
60
+
61
+ return {
62
+ ...periodForReferenceDate(lastEnd, plan.billingIntervalCount, plan.billingInterval),
63
+ isTrial: false,
64
+ };
65
+ },
66
+
67
+ shouldTriggerAction: async () => {
68
+ throw new Error(`Not implemented on EnrollmentAdapter`);
69
+ },
70
+ };
71
+ },
72
+
73
+ // eslint-disable-next-line
74
+ log(message: string, { level = LogLevel.Debug, ...options } = {}) {
75
+ return log(message, { level, ...options });
76
+ },
77
+ };