@lilaquadrat/studio 12.0.0 → 12.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/lib/models.d.ts +8 -1
  2. package/lib/models.js +8 -1
  3. package/lib/models.js.map +1 -1
  4. package/lib/services.d.ts +8 -1
  5. package/lib/services.js +8 -1
  6. package/lib/services.js.map +1 -1
  7. package/lib/src/Immutable.class.js +10 -4
  8. package/lib/src/Immutable.class.js.map +1 -1
  9. package/lib/src/aggegations/structures.aggregation.d.ts +6 -8
  10. package/lib/src/aggegations/structures.aggregation.js +3 -2
  11. package/lib/src/aggegations/structures.aggregation.js.map +1 -1
  12. package/lib/src/classes/paymentProviders/PaymentProviderFactory.class.d.ts +4 -0
  13. package/lib/src/classes/paymentProviders/PaymentProviderFactory.class.js +8 -0
  14. package/lib/src/classes/paymentProviders/PaymentProviderFactory.class.js.map +1 -0
  15. package/lib/src/classes/paymentProviders/StripePaymentProvider.class.d.ts +9 -0
  16. package/lib/src/classes/paymentProviders/StripePaymentProvider.class.js +49 -0
  17. package/lib/src/classes/paymentProviders/StripePaymentProvider.class.js.map +1 -0
  18. package/lib/src/classes/shiftPlanningModel.class.d.ts +6 -0
  19. package/lib/src/classes/shiftPlanningModel.class.js +26 -0
  20. package/lib/src/classes/shiftPlanningModel.class.js.map +1 -0
  21. package/lib/src/helpers/buildProductName.d.ts +7 -0
  22. package/lib/src/helpers/buildProductName.js +20 -0
  23. package/lib/src/helpers/buildProductName.js.map +1 -0
  24. package/lib/src/helpers/shiftPlanningReports.d.ts +7 -0
  25. package/lib/src/helpers/shiftPlanningReports.js +135 -0
  26. package/lib/src/helpers/shiftPlanningReports.js.map +1 -0
  27. package/lib/src/helpers/shiftPlanningSchemas.d.ts +143 -0
  28. package/lib/src/helpers/shiftPlanningSchemas.js +87 -0
  29. package/lib/src/helpers/shiftPlanningSchemas.js.map +1 -0
  30. package/lib/src/helpers/shiftPlanningTime.d.ts +24 -0
  31. package/lib/src/helpers/shiftPlanningTime.js +191 -0
  32. package/lib/src/helpers/shiftPlanningTime.js.map +1 -0
  33. package/lib/src/helpers/shiftPlanningValidation.d.ts +26 -0
  34. package/lib/src/helpers/shiftPlanningValidation.js +53 -0
  35. package/lib/src/helpers/shiftPlanningValidation.js.map +1 -0
  36. package/lib/src/helpers/structureMatch.d.ts +15 -0
  37. package/lib/src/helpers/structureMatch.js +70 -0
  38. package/lib/src/helpers/structureMatch.js.map +1 -0
  39. package/lib/src/interfaces/PaymentProviderBase.d.ts +14 -0
  40. package/lib/src/interfaces/PaymentProviderBase.js +2 -0
  41. package/lib/src/interfaces/PaymentProviderBase.js.map +1 -0
  42. package/lib/src/models/customers.model.js +10 -0
  43. package/lib/src/models/customers.model.js.map +1 -1
  44. package/lib/src/models/employeeAbsence.model.d.ts +4 -0
  45. package/lib/src/models/employeeAbsence.model.js +11 -0
  46. package/lib/src/models/employeeAbsence.model.js.map +1 -0
  47. package/lib/src/models/historySeen.model.d.ts +4 -0
  48. package/lib/src/models/historySeen.model.js +30 -0
  49. package/lib/src/models/historySeen.model.js.map +1 -0
  50. package/lib/src/models/listsParticipants.model.js +11 -0
  51. package/lib/src/models/listsParticipants.model.js.map +1 -1
  52. package/lib/src/models/permissions.model.js +28 -0
  53. package/lib/src/models/permissions.model.js.map +1 -1
  54. package/lib/src/models/shift.model.d.ts +4 -0
  55. package/lib/src/models/shift.model.js +17 -0
  56. package/lib/src/models/shift.model.js.map +1 -0
  57. package/lib/src/models/shiftPlan.model.d.ts +4 -0
  58. package/lib/src/models/shiftPlan.model.js +14 -0
  59. package/lib/src/models/shiftPlan.model.js.map +1 -0
  60. package/lib/src/models/shiftPlanDays.model.d.ts +4 -0
  61. package/lib/src/models/shiftPlanDays.model.js +15 -0
  62. package/lib/src/models/shiftPlanDays.model.js.map +1 -0
  63. package/lib/src/models/shiftPlanningSettings.model.d.ts +4 -0
  64. package/lib/src/models/shiftPlanningSettings.model.js +10 -0
  65. package/lib/src/models/shiftPlanningSettings.model.js.map +1 -0
  66. package/lib/src/models/workAreas.model.d.ts +4 -0
  67. package/lib/src/models/workAreas.model.js +12 -0
  68. package/lib/src/models/workAreas.model.js.map +1 -0
  69. package/lib/src/services/customers.service.d.ts +11 -0
  70. package/lib/src/services/customers.service.js +27 -0
  71. package/lib/src/services/customers.service.js.map +1 -1
  72. package/lib/src/services/employeeAbsences.service.d.ts +18 -0
  73. package/lib/src/services/employeeAbsences.service.js +57 -0
  74. package/lib/src/services/employeeAbsences.service.js.map +1 -0
  75. package/lib/src/services/history.service.d.ts +22 -0
  76. package/lib/src/services/history.service.js +145 -115
  77. package/lib/src/services/history.service.js.map +1 -1
  78. package/lib/src/services/historySeen.service.d.ts +32 -0
  79. package/lib/src/services/historySeen.service.js +66 -0
  80. package/lib/src/services/historySeen.service.js.map +1 -0
  81. package/lib/src/services/listParticipants.service.d.ts +143 -12
  82. package/lib/src/services/listParticipants.service.js +145 -6
  83. package/lib/src/services/listParticipants.service.js.map +1 -1
  84. package/lib/src/services/lists.service.d.ts +9 -0
  85. package/lib/src/services/lists.service.js +28 -0
  86. package/lib/src/services/lists.service.js.map +1 -1
  87. package/lib/src/services/paymentProviders.service.d.ts +5 -0
  88. package/lib/src/services/paymentProviders.service.js +10 -0
  89. package/lib/src/services/paymentProviders.service.js.map +1 -1
  90. package/lib/src/services/shiftPlanDays.service.d.ts +22 -0
  91. package/lib/src/services/shiftPlanDays.service.js +80 -0
  92. package/lib/src/services/shiftPlanDays.service.js.map +1 -0
  93. package/lib/src/services/shiftPlanningSettings.service.d.ts +11 -0
  94. package/lib/src/services/shiftPlanningSettings.service.js +27 -0
  95. package/lib/src/services/shiftPlanningSettings.service.js.map +1 -0
  96. package/lib/src/services/shiftPlans.service.d.ts +24 -0
  97. package/lib/src/services/shiftPlans.service.js +139 -0
  98. package/lib/src/services/shiftPlans.service.js.map +1 -0
  99. package/lib/src/services/shifts.service.d.ts +29 -0
  100. package/lib/src/services/shifts.service.js +260 -0
  101. package/lib/src/services/shifts.service.js.map +1 -0
  102. package/lib/src/services/structures.service.d.ts +2 -0
  103. package/lib/src/services/structures.service.js +7 -0
  104. package/lib/src/services/structures.service.js.map +1 -1
  105. package/lib/src/services/workAreas.service.d.ts +18 -0
  106. package/lib/src/services/workAreas.service.js +67 -0
  107. package/lib/src/services/workAreas.service.js.map +1 -0
  108. package/lib/tests/buildProductName.spec.d.ts +1 -0
  109. package/lib/tests/buildProductName.spec.js +27 -0
  110. package/lib/tests/buildProductName.spec.js.map +1 -0
  111. package/lib/tests/customersServiceStructures.spec.d.ts +1 -0
  112. package/lib/tests/customersServiceStructures.spec.js +146 -0
  113. package/lib/tests/customersServiceStructures.spec.js.map +1 -0
  114. package/lib/tests/historySeenService.spec.d.ts +1 -0
  115. package/lib/tests/historySeenService.spec.js +159 -0
  116. package/lib/tests/historySeenService.spec.js.map +1 -0
  117. package/lib/tests/listParticipantsHistory.spec.js +49 -3
  118. package/lib/tests/listParticipantsHistory.spec.js.map +1 -1
  119. package/lib/tests/listParticipantsPlanning.spec.d.ts +1 -0
  120. package/lib/tests/listParticipantsPlanning.spec.js +83 -0
  121. package/lib/tests/listParticipantsPlanning.spec.js.map +1 -0
  122. package/lib/tests/listParticipantsServiceStructures.spec.d.ts +1 -0
  123. package/lib/tests/listParticipantsServiceStructures.spec.js +176 -0
  124. package/lib/tests/listParticipantsServiceStructures.spec.js.map +1 -0
  125. package/lib/tests/listsServiceCreateExternalProducts.spec.d.ts +1 -0
  126. package/lib/tests/listsServiceCreateExternalProducts.spec.js +73 -0
  127. package/lib/tests/listsServiceCreateExternalProducts.spec.js.map +1 -0
  128. package/lib/tests/paymentProviders.spec.d.ts +1 -0
  129. package/lib/tests/paymentProviders.spec.js +119 -0
  130. package/lib/tests/paymentProviders.spec.js.map +1 -0
  131. package/lib/tests/paymentProvidersServiceGetProduct.spec.d.ts +1 -0
  132. package/lib/tests/paymentProvidersServiceGetProduct.spec.js +33 -0
  133. package/lib/tests/paymentProvidersServiceGetProduct.spec.js.map +1 -0
  134. package/lib/tests/shiftPlanning.spec.d.ts +1 -0
  135. package/lib/tests/shiftPlanning.spec.js +835 -0
  136. package/lib/tests/shiftPlanning.spec.js.map +1 -0
  137. package/lib/tests/structureMatch.spec.d.ts +1 -0
  138. package/lib/tests/structureMatch.spec.js +64 -0
  139. package/lib/tests/structureMatch.spec.js.map +1 -0
  140. package/package.json +2 -2
@@ -0,0 +1,176 @@
1
+ import { afterAll, beforeAll, beforeEach, describe, expect, it } from '@jest/globals';
2
+ import mongodb from 'mongo-mock';
3
+ import { ObjectId } from 'mongodb';
4
+ import Models from '../src/classes/models.class.js';
5
+ import ListParticipantsModel from '../src/models/listsParticipants.model.js';
6
+ import HistoryModel from '../src/models/history.model.js';
7
+ import StructureModel from '../src/models/structure.model.js';
8
+ import ListParticipantsService from '../src/services/listParticipants.service.js';
9
+ import StructureService from '../src/services/structures.service.js';
10
+ const listId = new ObjectId();
11
+ const participantId = new ObjectId();
12
+ const options = { user: 'studio-account', app: 'lists-app', company: 'company', project: 'project' };
13
+ const structures = [
14
+ {
15
+ _id: new ObjectId(),
16
+ id: 's-string-1',
17
+ model: 'listsParticipants',
18
+ company: options.company,
19
+ project: options.project,
20
+ type: 'string',
21
+ question: 'T-Shirt size',
22
+ max: 20,
23
+ },
24
+ {
25
+ _id: new ObjectId(),
26
+ id: 's-select-1',
27
+ model: 'listsParticipants',
28
+ company: options.company,
29
+ project: options.project,
30
+ type: 'select',
31
+ question: 'Meal',
32
+ options: [{ value: 'a', text: 'A' }, { value: 'b', text: 'B' }],
33
+ },
34
+ {
35
+ _id: new ObjectId(),
36
+ id: 's-multi-1',
37
+ model: 'listsParticipants',
38
+ company: options.company,
39
+ project: options.project,
40
+ type: 'select',
41
+ multiple: true,
42
+ question: 'Workshops',
43
+ options: [{ value: 'a', text: 'A' }, { value: 'b', text: 'B' }],
44
+ },
45
+ {
46
+ _id: new ObjectId(),
47
+ id: 's-bool-1',
48
+ model: 'listsParticipants',
49
+ company: options.company,
50
+ project: options.project,
51
+ type: 'boolean',
52
+ question: 'Vegetarian',
53
+ },
54
+ {
55
+ _id: new ObjectId(),
56
+ id: 's-number-1',
57
+ model: 'listsParticipants',
58
+ company: options.company,
59
+ project: options.project,
60
+ type: 'number',
61
+ question: 'Guests',
62
+ min: 1,
63
+ max: 10,
64
+ },
65
+ // listsParticipants structures are company and project scoped
66
+ ];
67
+ const participant = {
68
+ _id: participantId,
69
+ list: listId,
70
+ user: new ObjectId(),
71
+ category: 'cat-1',
72
+ state: 'reserved',
73
+ agreements: [],
74
+ company: options.company,
75
+ project: options.project,
76
+ history: { source: 'studio', version: 0 },
77
+ };
78
+ describe('list participant structure updates', () => {
79
+ let client;
80
+ beforeAll(async () => {
81
+ mongodb.max_delay = 0;
82
+ client = await mongodb.MongoClient.connect('mongodb://localhost:27017/list-participant-structures-tests');
83
+ const models = new Models();
84
+ models.register('listParticipants', ListParticipantsModel);
85
+ models.register('history', HistoryModel);
86
+ models.register('structures', StructureModel);
87
+ await Promise.all(models.injectDatabaseConnection(client, undefined, true));
88
+ // studio-api injects the configured Ajv instance at startup; mirror that here for structure validation.
89
+ StructureService.injectAjv(models.ajv);
90
+ });
91
+ beforeEach(async () => {
92
+ // mongo-mock's deleteMany compares cloned ObjectIds by identity and leaves documents behind.
93
+ for (const collection of [ListParticipantsModel.db, HistoryModel.db, StructureModel.db]) {
94
+ while (await collection.countDocuments({}))
95
+ await collection.deleteOne({});
96
+ }
97
+ await ListParticipantsModel.db.insertOne({ ...participant, _id: participantId, list: listId });
98
+ for (const structure of structures) {
99
+ await StructureModel.db.insertOne({ ...structure });
100
+ }
101
+ });
102
+ afterAll(async () => {
103
+ await client.close();
104
+ });
105
+ it.each([
106
+ { 's-string-1': 'L' },
107
+ { 's-select-1': 'a' },
108
+ { 's-multi-1': ['a', 'b'] },
109
+ { 's-bool-1': true },
110
+ { 's-bool-1': false },
111
+ { 's-number-1': 5 },
112
+ { 's-string-1': 'L', 's-select-1': 'b' },
113
+ ])('accepts a valid partial payload and persists it: %j', async (payload) => {
114
+ await ListParticipantsService.updateStructures(listId, participantId, payload, options);
115
+ const stored = await ListParticipantsModel.db.findOne({ _id: participantId });
116
+ Object.entries(payload).forEach(([key, value]) => expect(stored[key]).toEqual(value));
117
+ // every structure that is absent from the payload must be removed again
118
+ structures
119
+ .map((structure) => structure.id)
120
+ .filter((id) => !(id && id in payload))
121
+ .forEach((id) => expect(stored[id]).toBeUndefined());
122
+ });
123
+ it('clears every answer when the payload is empty', async () => {
124
+ await ListParticipantsModel.db.updateOne({ _id: participantId }, { $set: { 's-string-1': 'L', 's-bool-1': true } });
125
+ await ListParticipantsService.updateStructures(listId, participantId, {}, options);
126
+ const stored = await ListParticipantsModel.db.findOne({ _id: participantId });
127
+ expect(stored['s-string-1']).toBeUndefined();
128
+ expect(stored['s-bool-1']).toBeUndefined();
129
+ });
130
+ it('removes answers absent from the payload but keeps explicit false answers', async () => {
131
+ await ListParticipantsModel.db.updateOne({ _id: participantId }, { $set: { 's-string-1': 'L', 's-bool-1': true, 's-number-1': 3 } });
132
+ await ListParticipantsService.updateStructures(listId, participantId, { 's-bool-1': false }, options);
133
+ const stored = await ListParticipantsModel.db.findOne({ _id: participantId });
134
+ expect(stored['s-bool-1']).toBe(false);
135
+ expect(stored['s-string-1']).toBeUndefined();
136
+ expect(stored['s-number-1']).toBeUndefined();
137
+ });
138
+ it('rejects keys that do not start with s- even when a matching structure exists', async () => {
139
+ await StructureModel.db.insertOne({
140
+ _id: new ObjectId(),
141
+ id: 'custom-1',
142
+ model: 'listsParticipants',
143
+ company: options.company,
144
+ project: options.project,
145
+ type: 'string',
146
+ question: 'Legacy question',
147
+ });
148
+ await expect(ListParticipantsService.updateStructures(listId, participantId, { 'custom-1': 'x' }, options)).rejects.toThrow('VALIDATION_FAILED');
149
+ });
150
+ it('rejects a structure that belongs to another project', async () => {
151
+ await StructureModel.db.insertOne({
152
+ _id: new ObjectId(),
153
+ id: 's-foreign-1',
154
+ model: 'listsParticipants',
155
+ company: options.company,
156
+ project: 'other-project',
157
+ type: 'string',
158
+ question: 'Other project question',
159
+ });
160
+ await expect(ListParticipantsService.updateStructures(listId, participantId, { 's-foreign-1': 'x' }, options)).rejects.toThrow('VALIDATION_FAILED');
161
+ });
162
+ it.each([
163
+ { 's-unknown-1': 'x' },
164
+ { 's-string-1': 123 },
165
+ { 's-select-1': 'z' },
166
+ { 's-multi-1': ['a', 'z'] },
167
+ { 's-multi-1': 'a' },
168
+ { 's-bool-1': 'true' },
169
+ { 's-number-1': 11 },
170
+ { 's-number-1': 0 },
171
+ { 's-string-1': 'x'.repeat(21) },
172
+ ])('rejects a payload that does not match the structures: %j', async (payload) => {
173
+ await expect(ListParticipantsService.updateStructures(listId, participantId, payload, options)).rejects.toThrow('VALIDATION_FAILED');
174
+ });
175
+ });
176
+ //# sourceMappingURL=listParticipantsServiceStructures.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listParticipantsServiceStructures.spec.js","sourceRoot":"","sources":["../../tests/listParticipantsServiceStructures.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,eAAe,CAAC;AACtF,OAAO,OAAO,MAAM,YAAY,CAAC;AACjC,OAAO,EAAe,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEhD,OAAO,MAAM,MAAM,gCAAgC,CAAC;AACpD,OAAO,qBAAqB,MAAM,0CAA0C,CAAC;AAC7E,OAAO,YAAY,MAAM,gCAAgC,CAAC;AAC1D,OAAO,cAAc,MAAM,kCAAkC,CAAC;AAC9D,OAAO,uBAAuB,MAAM,6CAA6C,CAAC;AAClF,OAAO,gBAAgB,MAAM,uCAAuC,CAAC;AAErE,MAAM,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;AAC9B,MAAM,aAAa,GAAG,IAAI,QAAQ,EAAE,CAAC;AACrC,MAAM,OAAO,GAAG,EAAE,IAAI,EAAE,gBAAgB,EAAE,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AAErG,MAAM,UAAU,GAAG;IACjB;QACE,GAAG,EAAE,IAAI,QAAQ,EAAE;QACnB,EAAE,EAAE,YAAY;QAChB,KAAK,EAAE,mBAAmB;QAC1B,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,cAAc;QACxB,GAAG,EAAE,EAAE;KACR;IACD;QACE,GAAG,EAAE,IAAI,QAAQ,EAAE;QACnB,EAAE,EAAE,YAAY;QAChB,KAAK,EAAE,mBAAmB;QAC1B,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,MAAM;QAChB,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;KAChE;IACD;QACE,GAAG,EAAE,IAAI,QAAQ,EAAE;QACnB,EAAE,EAAE,WAAW;QACf,KAAK,EAAE,mBAAmB;QAC1B,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,IAAI;QACd,QAAQ,EAAE,WAAW;QACrB,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;KAChE;IACD;QACE,GAAG,EAAE,IAAI,QAAQ,EAAE;QACnB,EAAE,EAAE,UAAU;QACd,KAAK,EAAE,mBAAmB;QAC1B,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,IAAI,EAAE,SAAS;QACf,QAAQ,EAAE,YAAY;KACvB;IACD;QACE,GAAG,EAAE,IAAI,QAAQ,EAAE;QACnB,EAAE,EAAE,YAAY;QAChB,KAAK,EAAE,mBAAmB;QAC1B,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,QAAQ;QAClB,GAAG,EAAE,CAAC;QACN,GAAG,EAAE,EAAE;KACR;IACH,8DAA8D;CACxB,CAAC;AAEvC,MAAM,WAAW,GAAgC;IAC/C,GAAG,EAAE,aAAa;IAClB,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,IAAI,QAAQ,EAAE;IACpB,QAAQ,EAAE,OAAO;IACjB,KAAK,EAAE,UAAU;IACjB,UAAU,EAAE,EAAE;IACd,OAAO,EAAE,OAAO,CAAC,OAAO;IACxB,OAAO,EAAE,OAAO,CAAC,OAAO;IACxB,OAAO,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,EAAE;CAC1C,CAAC;AAEF,QAAQ,CAAC,oCAAoC,EAAE,GAAG,EAAE;IAElD,IAAI,MAAmB,CAAC;IAExB,SAAS,CAAC,KAAK,IAAI,EAAE;QAEnB,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC;QACtB,MAAM,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,6DAA6D,CAAgB,CAAC;QACzH,MAAM,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;QAC5B,MAAM,CAAC,QAAQ,CAAC,kBAAkB,EAAE,qBAAqB,CAAC,CAAC;QAC3D,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QACzC,MAAM,CAAC,QAAQ,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;QAC9C,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,wBAAwB,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC;QAC5E,wGAAwG;QACxG,gBAAgB,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAEzC,CAAC,CAAC,CAAC;IAEH,UAAU,CAAC,KAAK,IAAI,EAAE;QAEpB,6FAA6F;QAC7F,KAAK,MAAM,UAAU,IAAI,CAAC,qBAAqB,CAAC,EAAE,EAAE,YAAY,CAAC,EAAE,EAAE,cAAc,CAAC,EAAE,CAAC,EAAE,CAAC;YAExF,OAAO,MAAM,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;gBAAE,MAAM,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QAE7E,CAAC;QACD,MAAM,qBAAqB,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,GAAG,WAAW,EAAE,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;QAE/F,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YAEnC,MAAM,cAAc,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,GAAG,SAAS,EAAE,CAAC,CAAC;QAEtD,CAAC;IAEH,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,KAAK,IAAI,EAAE;QAElB,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IAEvB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,IAAI,CAAC;QACN,EAAE,YAAY,EAAE,GAAG,EAAE;QACrB,EAAE,YAAY,EAAE,GAAG,EAAE;QACrB,EAAE,WAAW,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE;QAC3B,EAAE,UAAU,EAAE,IAAI,EAAE;QACpB,EAAE,UAAU,EAAE,KAAK,EAAE;QACrB,EAAE,YAAY,EAAE,CAAC,EAAE;QACnB,EAAE,YAAY,EAAE,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE;KACzC,CAAC,CAAC,qDAAqD,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QAE1E,MAAM,uBAAuB,CAAC,gBAAgB,CAAC,MAAM,EAAE,aAAa,EAAE,OAA0E,EAAE,OAAO,CAAC,CAAC;QAE3J,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,aAAa,EAAE,CAAuC,CAAC;QAEpH,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QACtF,wEAAwE;QACxE,UAAU;aACP,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC;aAChC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,OAAO,CAAC,CAAC;aACtC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,EAAY,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC;IAEnE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;QAE7D,MAAM,qBAAqB,CAAC,EAAE,CAAC,SAAS,CACtC,EAAE,GAAG,EAAE,aAAa,EAAE,EACtB,EAAE,IAAI,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,CAClD,CAAC;QAEF,MAAM,uBAAuB,CAAC,gBAAgB,CAAC,MAAM,EAAE,aAAa,EAAE,EAA0D,EAAE,OAAO,CAAC,CAAC;QAE3I,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,aAAa,EAAE,CAAuC,CAAC;QAEpH,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;QAC7C,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IAE7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0EAA0E,EAAE,KAAK,IAAI,EAAE;QAExF,MAAM,qBAAqB,CAAC,EAAE,CAAC,SAAS,CACtC,EAAE,GAAG,EAAE,aAAa,EAAE,EACtB,EAAE,IAAI,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,EAAE,EAAE,CACnE,CAAC;QAEF,MAAM,uBAAuB,CAAC,gBAAgB,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,UAAU,EAAE,KAAK,EAAqE,EAAE,OAAO,CAAC,CAAC;QAEzK,MAAM,MAAM,GAAG,MAAM,qBAAqB,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,aAAa,EAAE,CAAuC,CAAC;QAEpH,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;QAC7C,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IAE/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8EAA8E,EAAE,KAAK,IAAI,EAAE;QAE5F,MAAM,cAAc,CAAC,EAAE,CAAC,SAAS,CAAC;YAChC,GAAG,EAAE,IAAI,QAAQ,EAAE;YACnB,EAAE,EAAE,UAAU;YACd,KAAK,EAAE,mBAAmB;YAC1B,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,iBAAiB;SAC5B,CAAC,CAAC;QAEH,MAAM,MAAM,CAAC,uBAAuB,CAAC,gBAAgB,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,UAAU,EAAE,GAAG,EAAuC,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAExL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QAEnE,MAAM,cAAc,CAAC,EAAE,CAAC,SAAS,CAAC;YAChC,GAAG,EAAE,IAAI,QAAQ,EAAE;YACnB,EAAE,EAAE,aAAa;YACjB,KAAK,EAAE,mBAAmB;YAC1B,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,OAAO,EAAE,eAAe;YACxB,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,wBAAwB;SACnC,CAAC,CAAC;QAEH,MAAM,MAAM,CAAC,uBAAuB,CAAC,gBAAgB,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,aAAa,EAAE,GAAG,EAAuC,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAE3L,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,IAAI,CAAC;QACN,EAAE,aAAa,EAAE,GAAG,EAAE;QACtB,EAAE,YAAY,EAAE,GAAG,EAAE;QACrB,EAAE,YAAY,EAAE,GAAG,EAAE;QACrB,EAAE,WAAW,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE;QAC3B,EAAE,WAAW,EAAE,GAAG,EAAE;QACpB,EAAE,UAAU,EAAE,MAAM,EAAE;QACtB,EAAE,YAAY,EAAE,EAAE,EAAE;QACpB,EAAE,YAAY,EAAE,CAAC,EAAE;QACnB,EAAE,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE;KACjC,CAAC,CAAC,0DAA0D,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QAE/E,MAAM,MAAM,CAAC,uBAAuB,CAAC,gBAAgB,CAAC,MAAM,EAAE,aAAa,EAAE,OAA0E,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAE1M,CAAC,CAAC,CAAC;AAEL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,73 @@
1
+ import { afterEach, beforeEach, describe, expect, it, jest } from '@jest/globals';
2
+ import { ObjectId } from 'mongodb';
3
+ const productsCreate = jest.fn();
4
+ class StripeMock {
5
+ constructor() {
6
+ this.products = { create: productsCreate };
7
+ }
8
+ }
9
+ jest.unstable_mockModule('stripe', () => ({ __esModule: true, default: StripeMock }));
10
+ const { default: listsService } = await import('../src/services/lists.service');
11
+ const { default: paymentProvidersService } = await import('../src/services/paymentProviders.service');
12
+ const options = { company: 'company', project: 'project', user: 'user', app: 'app' };
13
+ const stripeProvider = { type: 'stripe', active: true, label: 'stripe', token: 'sk_test', validationKey: 'whsec' };
14
+ const category = (overrides = {}) => ({
15
+ _id: new ObjectId(),
16
+ id: 'category',
17
+ name: 'Ticket',
18
+ price: { amount: 10, currency: 'eur', tax: 19 },
19
+ ...overrides,
20
+ });
21
+ const list = (categories) => ({ name: 'List 1', location: 'Leipzig', start: '2026-01-21T18:00:00.000Z', categories });
22
+ describe('ListsService.createExternalProducts', () => {
23
+ beforeEach(() => {
24
+ productsCreate.mockReset().mockResolvedValue({ id: 'prod_123' });
25
+ });
26
+ afterEach(() => {
27
+ jest.restoreAllMocks();
28
+ });
29
+ it('does nothing for a list without categories', async () => {
30
+ const byType = jest.spyOn(paymentProvidersService, 'byType');
31
+ await listsService.createExternalProducts(list(), options);
32
+ expect(byType).not.toHaveBeenCalled();
33
+ });
34
+ it('creates the product for a flagged category, stores the externalId and removes the flag', async () => {
35
+ const byType = jest.spyOn(paymentProvidersService, 'byType').mockResolvedValue(stripeProvider);
36
+ const data = list([category({ createExternalProduct: 'stripe' })]);
37
+ await listsService.createExternalProducts(data, options);
38
+ expect(byType).toHaveBeenCalledWith('stripe', 'company', 'project');
39
+ expect(data.categories?.[0].externalId).toBe('prod_123');
40
+ expect(data.categories?.[0]).not.toHaveProperty('createExternalProduct');
41
+ });
42
+ it('names the product after the list, its location, date and the category', async () => {
43
+ jest.spyOn(paymentProvidersService, 'byType').mockResolvedValue(stripeProvider);
44
+ await listsService.createExternalProducts(list([category({ createExternalProduct: 'stripe' })]), options);
45
+ expect(productsCreate).toHaveBeenCalledWith(expect.objectContaining({ name: 'List 1 - Leipzig - 21.01.2026 - Ticket' }));
46
+ });
47
+ it('leaves categories without the flag untouched', async () => {
48
+ const byType = jest.spyOn(paymentProvidersService, 'byType');
49
+ const data = list([category({ externalId: 'prod_existing' }), category()]);
50
+ await listsService.createExternalProducts(data, options);
51
+ expect(byType).not.toHaveBeenCalled();
52
+ expect(data.categories?.[0].externalId).toBe('prod_existing');
53
+ expect(data.categories?.[1].externalId).toBeUndefined();
54
+ });
55
+ it('keeps an existing externalId and still removes the flag', async () => {
56
+ const byType = jest.spyOn(paymentProvidersService, 'byType');
57
+ const data = list([category({ externalId: 'prod_existing', createExternalProduct: 'stripe' })]);
58
+ await listsService.createExternalProducts(data, options);
59
+ expect(byType).not.toHaveBeenCalled();
60
+ expect(productsCreate).not.toHaveBeenCalled();
61
+ expect(data.categories?.[0].externalId).toBe('prod_existing');
62
+ expect(data.categories?.[0]).not.toHaveProperty('createExternalProduct');
63
+ });
64
+ it('throws when no active provider of the requested type exists', async () => {
65
+ jest.spyOn(paymentProvidersService, 'byType').mockResolvedValue(null);
66
+ await expect(listsService.createExternalProducts(list([category({ createExternalProduct: 'stripe' })]), options)).rejects.toThrow('NO_PAYMENT_PROVIDER');
67
+ });
68
+ it('throws when the provider type has no implementation', async () => {
69
+ jest.spyOn(paymentProvidersService, 'byType').mockResolvedValue({ type: 'shopify', active: true, label: 'shopify' });
70
+ await expect(listsService.createExternalProducts(list([category({ createExternalProduct: 'shopify' })]), options)).rejects.toThrow('PAYMENT_PROVIDER_UNAVAILABLE_SHOPIFY');
71
+ });
72
+ });
73
+ //# sourceMappingURL=listsServiceCreateExternalProducts.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listsServiceCreateExternalProducts.spec.js","sourceRoot":"","sources":["../../tests/listsServiceCreateExternalProducts.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,119 @@
1
+ import { beforeEach, describe, expect, it, jest } from '@jest/globals';
2
+ import { ObjectId } from 'mongodb';
3
+ const productsCreate = jest.fn();
4
+ const productsRetrieve = jest.fn();
5
+ const stripeConstructor = jest.fn();
6
+ class StripeMock {
7
+ constructor(...arguments_) {
8
+ this.products = { create: productsCreate, retrieve: productsRetrieve };
9
+ stripeConstructor(...arguments_);
10
+ }
11
+ }
12
+ jest.unstable_mockModule('stripe', () => ({ __esModule: true, default: StripeMock }));
13
+ const { default: PaymentProviderFactory } = await import('../src/classes/paymentProviders/PaymentProviderFactory.class');
14
+ const { default: StripePaymentProvider } = await import('../src/classes/paymentProviders/StripePaymentProvider.class');
15
+ const stripeProvider = { type: 'stripe', active: true, label: 'stripe', token: 'sk_test', validationKey: 'whsec' };
16
+ const list = { name: 'List 1', location: 'Leipzig', start: '2026-01-21T18:00:00.000Z' };
17
+ const category = (overrides = {}) => ({
18
+ _id: new ObjectId(),
19
+ id: 'category',
20
+ name: 'Ticket',
21
+ description: 'Entry ticket',
22
+ price: { amount: 19.99, currency: 'eur', tax: 19 },
23
+ ...overrides,
24
+ });
25
+ describe('PaymentProviderFactory', () => {
26
+ it('returns the stripe implementation for a stripe provider', () => {
27
+ const instance = PaymentProviderFactory(stripeProvider);
28
+ expect(instance).toBeInstanceOf(StripePaymentProvider);
29
+ expect(instance.provider).toBe(stripeProvider);
30
+ });
31
+ it('throws for a provider type without an implementation', () => {
32
+ const shopifyProvider = { type: 'shopify', active: true, label: 'shopify' };
33
+ expect(() => PaymentProviderFactory(shopifyProvider)).toThrow('PAYMENT_PROVIDER_UNAVAILABLE_SHOPIFY');
34
+ });
35
+ });
36
+ describe('StripePaymentProvider', () => {
37
+ beforeEach(() => {
38
+ productsCreate.mockReset().mockResolvedValue({ id: 'prod_123' });
39
+ productsRetrieve.mockReset();
40
+ stripeConstructor.mockClear();
41
+ });
42
+ it('authenticates with the provider token', () => {
43
+ new StripePaymentProvider(stripeProvider);
44
+ expect(stripeConstructor).toHaveBeenCalledWith('sk_test');
45
+ });
46
+ it('creates a product with its default price in the smallest currency unit and returns the product id', async () => {
47
+ const productId = await new StripePaymentProvider(stripeProvider).createProduct(category(), list);
48
+ expect(productId).toBe('prod_123');
49
+ expect(productsCreate).toHaveBeenCalledWith({
50
+ name: 'List 1 - Leipzig - 21.01.2026 - Ticket',
51
+ description: 'Entry ticket',
52
+ default_price_data: { currency: 'eur', unit_amount: 1999 },
53
+ });
54
+ });
55
+ it('omits an empty description', async () => {
56
+ await new StripePaymentProvider(stripeProvider).createProduct(category({ description: '' }), list);
57
+ expect(productsCreate).toHaveBeenCalledWith(expect.objectContaining({ description: undefined }));
58
+ });
59
+ it('rejects a category without amount or currency', async () => {
60
+ const provider = new StripePaymentProvider(stripeProvider);
61
+ await expect(provider.createProduct(category({ price: { currency: 'eur' } }), list)).rejects.toThrow('CATEGORY_PRICE_MISSING');
62
+ await expect(provider.createProduct(category({ price: { amount: 5 } }), list)).rejects.toThrow('CATEGORY_PRICE_MISSING');
63
+ await expect(provider.createProduct(category({ price: undefined }), list)).rejects.toThrow('CATEGORY_PRICE_MISSING');
64
+ expect(productsCreate).not.toHaveBeenCalled();
65
+ });
66
+ describe('getProduct', () => {
67
+ const stripeProduct = (overrides = {}) => ({
68
+ id: 'prod_123',
69
+ name: 'List 1 - Leipzig - 21.01.2026 - Ticket',
70
+ description: 'Entry ticket',
71
+ active: true,
72
+ livemode: false,
73
+ default_price: { unit_amount: 1999, currency: 'eur' },
74
+ ...overrides,
75
+ });
76
+ it('loads the product with its expanded default price in major units', async () => {
77
+ productsRetrieve.mockResolvedValue(stripeProduct());
78
+ const product = await new StripePaymentProvider(stripeProvider).getProduct('prod_123');
79
+ expect(productsRetrieve).toHaveBeenCalledWith('prod_123', { expand: ['default_price'] });
80
+ expect(product).toEqual({
81
+ id: 'prod_123',
82
+ name: 'List 1 - Leipzig - 21.01.2026 - Ticket',
83
+ description: 'Entry ticket',
84
+ active: true,
85
+ price: { amount: 19.99, currency: 'eur' },
86
+ url: 'https://dashboard.stripe.com/test/products/prod_123',
87
+ });
88
+ });
89
+ it('links live mode products without the test segment', async () => {
90
+ productsRetrieve.mockResolvedValue(stripeProduct({ livemode: true }));
91
+ const product = await new StripePaymentProvider(stripeProvider).getProduct('prod_123');
92
+ expect(product.url).toBe('https://dashboard.stripe.com/products/prod_123');
93
+ });
94
+ it('omits the price if there is no flat default price', async () => {
95
+ const provider = new StripePaymentProvider(stripeProvider);
96
+ productsRetrieve.mockResolvedValueOnce(stripeProduct({ default_price: null }));
97
+ expect((await provider.getProduct('prod_123')).price).toBeUndefined();
98
+ productsRetrieve.mockResolvedValueOnce(stripeProduct({ default_price: 'price_123' }));
99
+ expect((await provider.getProduct('prod_123')).price).toBeUndefined();
100
+ productsRetrieve.mockResolvedValueOnce(stripeProduct({ default_price: { unit_amount: null, currency: 'eur' } }));
101
+ expect((await provider.getProduct('prod_123')).price).toBeUndefined();
102
+ });
103
+ it('omits an empty description and reports archived products', async () => {
104
+ productsRetrieve.mockResolvedValue(stripeProduct({ description: null, active: false }));
105
+ const product = await new StripePaymentProvider(stripeProvider).getProduct('prod_123');
106
+ expect(product.description).toBeUndefined();
107
+ expect(product.active).toBe(false);
108
+ });
109
+ it('maps an unknown product to PRODUCT_NOT_FOUND', async () => {
110
+ productsRetrieve.mockRejectedValue(Object.assign(new Error('No such product'), { code: 'resource_missing' }));
111
+ await expect(new StripePaymentProvider(stripeProvider).getProduct('prod_missing')).rejects.toThrow('PRODUCT_NOT_FOUND');
112
+ });
113
+ it('passes other provider errors through', async () => {
114
+ productsRetrieve.mockRejectedValue(Object.assign(new Error('Invalid API Key'), { code: 'api_key_invalid' }));
115
+ await expect(new StripePaymentProvider(stripeProvider).getProduct('prod_123')).rejects.toThrow('Invalid API Key');
116
+ });
117
+ });
118
+ });
119
+ //# sourceMappingURL=paymentProviders.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paymentProviders.spec.js","sourceRoot":"","sources":["../../tests/paymentProviders.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAEvE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,MAAM,cAAc,GAAG,IAAI,CAAC,EAAE,EAAyD,CAAC;AACxF,MAAM,gBAAgB,GAAG,IAAI,CAAC,EAAE,EAAkD,CAAC;AACnF,MAAM,iBAAiB,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;AAEpC,MAAM,UAAU;IAId,YAAY,GAAG,UAAqB;QAFpC,aAAQ,GAAG,EAAE,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC;QAIhE,iBAAiB,CAAC,GAAG,UAAU,CAAC,CAAC;IAEnC,CAAC;CAEF;AAED,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC;AAEtF,MAAM,EAAE,OAAO,EAAE,sBAAsB,EAAE,GAAG,MAAM,MAAM,CAAC,8DAA8D,CAAC,CAAC;AACzH,MAAM,EAAE,OAAO,EAAE,qBAAqB,EAAE,GAAG,MAAM,MAAM,CAAC,6DAA6D,CAAC,CAAC;AAEvH,MAAM,cAAc,GAA0B,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC;AAE1I,MAAM,IAAI,GAA8C,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,0BAA0B,EAAE,CAAC;AAEnI,MAAM,QAAQ,GAAG,CAAC,YAAmC,EAAE,EAAgB,EAAE,CAAC,CAAC;IACzE,GAAG,EAAE,IAAI,QAAQ,EAAE;IACnB,EAAE,EAAE,UAAU;IACd,IAAI,EAAE,QAAQ;IACd,WAAW,EAAE,cAAc;IAC3B,KAAK,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,EAAE;IAClD,GAAG,SAAS;CACb,CAAC,CAAC;AAEH,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IAEtC,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QAEjE,MAAM,QAAQ,GAAG,sBAAsB,CAAC,cAAc,CAAC,CAAC;QAExD,MAAM,CAAC,QAAQ,CAAC,CAAC,cAAc,CAAC,qBAAqB,CAAC,CAAC;QACvD,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAEjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAE9D,MAAM,eAAe,GAAoB,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;QAE7F,MAAM,CAAC,GAAG,EAAE,CAAC,sBAAsB,CAAC,eAAe,CAAC,CAAC,CAAC,OAAO,CAAC,sCAAsC,CAAC,CAAC;IAExG,CAAC,CAAC,CAAC;AAEL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IAErC,UAAU,CAAC,GAAG,EAAE;QAEd,cAAc,CAAC,SAAS,EAAE,CAAC,iBAAiB,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;QACjE,gBAAgB,CAAC,SAAS,EAAE,CAAC;QAC7B,iBAAiB,CAAC,SAAS,EAAE,CAAC;IAEhC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAE/C,IAAI,qBAAqB,CAAC,cAAc,CAAC,CAAC;QAE1C,MAAM,CAAC,iBAAiB,CAAC,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC;IAE5D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mGAAmG,EAAE,KAAK,IAAI,EAAE;QAEjH,MAAM,SAAS,GAAG,MAAM,IAAI,qBAAqB,CAAC,cAAc,CAAC,CAAC,aAAa,CAAC,QAAQ,EAAE,EAAE,IAAI,CAAC,CAAC;QAElG,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACnC,MAAM,CAAC,cAAc,CAAC,CAAC,oBAAoB,CAAC;YAC1C,IAAI,EAAE,wCAAwC;YAC9C,WAAW,EAAE,cAAc;YAC3B,kBAAkB,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE;SAC3D,CAAC,CAAC;IAEL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;QAE1C,MAAM,IAAI,qBAAqB,CAAC,cAAc,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;QAEnG,MAAM,CAAC,cAAc,CAAC,CAAC,oBAAoB,CAAC,MAAM,CAAC,gBAAgB,CAAC,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;IAEnG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;QAE7D,MAAM,QAAQ,GAAG,IAAI,qBAAqB,CAAC,cAAc,CAAC,CAAC;QAE3D,MAAM,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,wBAAwB,CAAC,CAAC;QAC/H,MAAM,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,wBAAwB,CAAC,CAAC;QACzH,MAAM,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,wBAAwB,CAAC,CAAC;QACrH,MAAM,CAAC,cAAc,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IAEhD,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;QAE1B,MAAM,aAAa,GAAG,CAAC,YAAqC,EAAE,EAAE,EAAE,CAAC,CAAC;YAClE,EAAE,EAAE,UAAU;YACd,IAAI,EAAE,wCAAwC;YAC9C,WAAW,EAAE,cAAc;YAC3B,MAAM,EAAE,IAAI;YACZ,QAAQ,EAAE,KAAK;YACf,aAAa,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE;YACrD,GAAG,SAAS;SACb,CAAC,CAAC;QAEH,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;YAEhF,gBAAgB,CAAC,iBAAiB,CAAC,aAAa,EAAE,CAAC,CAAC;YAEpD,MAAM,OAAO,GAAG,MAAM,IAAI,qBAAqB,CAAC,cAAc,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;YAEvF,MAAM,CAAC,gBAAgB,CAAC,CAAC,oBAAoB,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;YACzF,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC;gBACtB,EAAE,EAAE,UAAU;gBACd,IAAI,EAAE,wCAAwC;gBAC9C,WAAW,EAAE,cAAc;gBAC3B,MAAM,EAAE,IAAI;gBACZ,KAAK,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE;gBACzC,GAAG,EAAE,qDAAqD;aAC3D,CAAC,CAAC;QAEL,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;YAEjE,gBAAgB,CAAC,iBAAiB,CAAC,aAAa,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YAEtE,MAAM,OAAO,GAAG,MAAM,IAAI,qBAAqB,CAAC,cAAc,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;YAEvF,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC;QAE7E,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;YAEjE,MAAM,QAAQ,GAAG,IAAI,qBAAqB,CAAC,cAAc,CAAC,CAAC;YAE3D,gBAAgB,CAAC,qBAAqB,CAAC,aAAa,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YAC/E,MAAM,CAAC,CAAC,MAAM,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,aAAa,EAAE,CAAC;YAEtE,gBAAgB,CAAC,qBAAqB,CAAC,aAAa,CAAC,EAAE,aAAa,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;YACtF,MAAM,CAAC,CAAC,MAAM,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,aAAa,EAAE,CAAC;YAEtE,gBAAgB,CAAC,qBAAqB,CAAC,aAAa,CAAC,EAAE,aAAa,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC;YACjH,MAAM,CAAC,CAAC,MAAM,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,aAAa,EAAE,CAAC;QAExE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;YAExE,gBAAgB,CAAC,iBAAiB,CAAC,aAAa,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;YAExF,MAAM,OAAO,GAAG,MAAM,IAAI,qBAAqB,CAAC,cAAc,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;YAEvF,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,aAAa,EAAE,CAAC;YAC5C,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAErC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;YAE5D,gBAAgB,CAAC,iBAAiB,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,iBAAiB,CAAC,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC;YAE9G,MAAM,MAAM,CAAC,IAAI,qBAAqB,CAAC,cAAc,CAAC,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;QAE1H,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;YAEpD,gBAAgB,CAAC,iBAAiB,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,iBAAiB,CAAC,EAAE,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC,CAAC,CAAC;YAE7G,MAAM,MAAM,CAAC,IAAI,qBAAqB,CAAC,cAAc,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;QAEpH,CAAC,CAAC,CAAC;IAEL,CAAC,CAAC,CAAC;AAEL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,33 @@
1
+ import { afterEach, describe, expect, it, jest } from '@jest/globals';
2
+ const productsRetrieve = jest.fn();
3
+ class StripeMock {
4
+ constructor() {
5
+ this.products = { retrieve: productsRetrieve };
6
+ }
7
+ }
8
+ jest.unstable_mockModule('stripe', () => ({ __esModule: true, default: StripeMock }));
9
+ const { default: paymentProvidersService } = await import('../src/services/paymentProviders.service');
10
+ const stripeProvider = { type: 'stripe', active: true, label: 'stripe', token: 'sk_test', validationKey: 'whsec' };
11
+ describe('PaymentProvidersService.getProduct', () => {
12
+ afterEach(() => {
13
+ jest.restoreAllMocks();
14
+ productsRetrieve.mockReset();
15
+ });
16
+ it('loads the product from the active provider of the requested type', async () => {
17
+ const byType = jest.spyOn(paymentProvidersService, 'byType').mockResolvedValue(stripeProvider);
18
+ productsRetrieve.mockResolvedValue({ id: 'prod_123', name: 'Ticket', active: true, livemode: true, default_price: null });
19
+ const product = await paymentProvidersService.getProduct('stripe', 'prod_123', 'company', 'project');
20
+ expect(byType).toHaveBeenCalledWith('stripe', 'company', 'project');
21
+ expect(product).toEqual(expect.objectContaining({ id: 'prod_123', name: 'Ticket', active: true }));
22
+ });
23
+ it('throws when no active provider of that type exists', async () => {
24
+ jest.spyOn(paymentProvidersService, 'byType').mockResolvedValue(null);
25
+ await expect(paymentProvidersService.getProduct('stripe', 'prod_123', 'company', 'project')).rejects.toThrow('NO_PAYMENT_PROVIDER');
26
+ expect(productsRetrieve).not.toHaveBeenCalled();
27
+ });
28
+ it('throws when the provider type has no implementation', async () => {
29
+ jest.spyOn(paymentProvidersService, 'byType').mockResolvedValue({ type: 'shopify', active: true, label: 'shopify' });
30
+ await expect(paymentProvidersService.getProduct('shopify', 'prod_123', 'company', 'project')).rejects.toThrow('PAYMENT_PROVIDER_UNAVAILABLE_SHOPIFY');
31
+ });
32
+ });
33
+ //# sourceMappingURL=paymentProvidersServiceGetProduct.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paymentProvidersServiceGetProduct.spec.js","sourceRoot":"","sources":["../../tests/paymentProvidersServiceGetProduct.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAGtE,MAAM,gBAAgB,GAAG,IAAI,CAAC,EAAE,EAAkD,CAAC;AAEnF,MAAM,UAAU;IAAhB;QAEE,aAAQ,GAAG,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAE5C,CAAC;CAAA;AAED,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC;AAEtF,MAAM,EAAE,OAAO,EAAE,uBAAuB,EAAE,GAAG,MAAM,MAAM,CAAC,0CAA0C,CAAC,CAAC;AAEtG,MAAM,cAAc,GAA0B,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC;AAE1I,QAAQ,CAAC,oCAAoC,EAAE,GAAG,EAAE;IAElD,SAAS,CAAC,GAAG,EAAE;QAEb,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,gBAAgB,CAAC,SAAS,EAAE,CAAC;IAE/B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;QAEhF,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,uBAAuB,EAAE,QAAQ,CAAC,CAAC,iBAAiB,CAAC,cAAc,CAAC,CAAC;QAC/F,gBAAgB,CAAC,iBAAiB,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAE1H,MAAM,OAAO,GAAG,MAAM,uBAAuB,CAAC,UAAU,CAAC,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;QAErG,MAAM,CAAC,MAAM,CAAC,CAAC,oBAAoB,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;QACpE,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAErG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAElE,IAAI,CAAC,KAAK,CAAC,uBAAuB,EAAE,QAAQ,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;QAEtE,MAAM,MAAM,CAAC,uBAAuB,CAAC,UAAU,CAAC,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC;QACpI,MAAM,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IAElD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QAEnE,IAAI,CAAC,KAAK,CAAC,uBAAuB,EAAE,QAAQ,CAAC,CAAC,iBAAiB,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QAErH,MAAM,MAAM,CAAC,uBAAuB,CAAC,UAAU,CAAC,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,sCAAsC,CAAC,CAAC;IAExJ,CAAC,CAAC,CAAC;AAEL,CAAC,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export {};