@unchainedshop/core 4.5.0 → 4.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/bulk-exporter/createBulkExporter.d.ts +33 -0
- package/lib/bulk-exporter/createBulkExporter.js +46 -0
- package/lib/bulk-exporter/handlers/exportAssortmentsHandler.d.ts +38 -0
- package/lib/bulk-exporter/handlers/exportAssortmentsHandler.js +137 -0
- package/lib/bulk-exporter/handlers/exportFiltersHandler.d.ts +26 -0
- package/lib/bulk-exporter/handlers/exportFiltersHandler.js +88 -0
- package/lib/bulk-exporter/handlers/exportProductsHandler.d.ts +40 -0
- package/lib/bulk-exporter/handlers/exportProductsHandler.js +238 -0
- package/lib/bulk-exporter/handlers/exportUsersHandler.d.ts +40 -0
- package/lib/bulk-exporter/handlers/exportUsersHandler.js +340 -0
- package/lib/bulk-exporter/handlers/generateCSVFileAndUrl.d.ts +13 -0
- package/lib/bulk-exporter/handlers/generateCSVFileAndUrl.js +21 -0
- package/lib/bulk-exporter/handlers/toCSV.d.ts +2 -0
- package/lib/bulk-exporter/handlers/toCSV.js +5 -0
- package/lib/bulk-exporter/index.d.ts +3 -0
- package/lib/bulk-exporter/index.js +3 -0
- package/lib/bulk-importer/handlers/assortment/create.d.ts +0 -2
- package/lib/bulk-importer/handlers/assortment/create.js +0 -1
- package/lib/bulk-importer/handlers/assortment/update.d.ts +0 -2
- package/lib/bulk-importer/handlers/assortment/update.js +0 -1
- package/lib/bulk-importer/handlers/product/create.js +2 -2
- package/lib/bulk-importer/handlers/product/update.js +2 -2
- package/lib/core-index.d.ts +7 -1
- package/lib/core-index.js +5 -1
- package/lib/directors/EnrollmentDirector.d.ts +4 -1
- package/lib/directors/PaymentDirector.js +2 -0
- package/lib/directors/WorkerAdapter.d.ts +2 -0
- package/lib/services/fulfillQuotation.d.ts +3 -0
- package/lib/services/{fullfillQuotation.js → fulfillQuotation.js} +3 -3
- package/lib/services/index.d.ts +2 -2
- package/lib/services/index.js +2 -2
- package/lib/services/processOrder.js +17 -9
- package/lib/services/rejectQuotation.js +1 -1
- package/package.json +21 -20
- package/lib/services/fullfillQuotation.d.ts +0 -3
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { UnchainedCore } from '../../core-index.ts';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
export declare const UserExportPayloadSchema: z.ZodObject<{
|
|
4
|
+
exportReviews: z.ZodOptional<z.ZodBoolean>;
|
|
5
|
+
exportOrders: z.ZodOptional<z.ZodBoolean>;
|
|
6
|
+
exportBookmarks: z.ZodOptional<z.ZodBoolean>;
|
|
7
|
+
exportEvents: z.ZodOptional<z.ZodBoolean>;
|
|
8
|
+
exportQuotations: z.ZodOptional<z.ZodBoolean>;
|
|
9
|
+
exportEnrollments: z.ZodOptional<z.ZodBoolean>;
|
|
10
|
+
userId: z.ZodOptional<z.ZodString>;
|
|
11
|
+
}, z.core.$strip>;
|
|
12
|
+
export interface UserExportParams {
|
|
13
|
+
exportReviews?: boolean;
|
|
14
|
+
exportOrders?: boolean;
|
|
15
|
+
exportBookmarks?: boolean;
|
|
16
|
+
exportEvents?: boolean;
|
|
17
|
+
exportQuotations?: boolean;
|
|
18
|
+
exportEnrollments?: boolean;
|
|
19
|
+
userId: string;
|
|
20
|
+
}
|
|
21
|
+
declare const exportUsersHandler: {
|
|
22
|
+
({ userId, ...options }: UserExportParams, _: any, unchainedAPI: UnchainedCore): Promise<{
|
|
23
|
+
user: import("./generateCSVFileAndUrl.ts").CSVFileResult;
|
|
24
|
+
bookmarks: import("./generateCSVFileAndUrl.ts").CSVFileResult | null;
|
|
25
|
+
orders: import("./generateCSVFileAndUrl.ts").CSVFileResult | null;
|
|
26
|
+
reviews: import("./generateCSVFileAndUrl.ts").CSVFileResult | null;
|
|
27
|
+
quotations: import("./generateCSVFileAndUrl.ts").CSVFileResult | null;
|
|
28
|
+
enrollments: import("./generateCSVFileAndUrl.ts").CSVFileResult | null;
|
|
29
|
+
}>;
|
|
30
|
+
payloadSchema: z.ZodObject<{
|
|
31
|
+
exportReviews: z.ZodOptional<z.ZodBoolean>;
|
|
32
|
+
exportOrders: z.ZodOptional<z.ZodBoolean>;
|
|
33
|
+
exportBookmarks: z.ZodOptional<z.ZodBoolean>;
|
|
34
|
+
exportEvents: z.ZodOptional<z.ZodBoolean>;
|
|
35
|
+
exportQuotations: z.ZodOptional<z.ZodBoolean>;
|
|
36
|
+
exportEnrollments: z.ZodOptional<z.ZodBoolean>;
|
|
37
|
+
userId: z.ZodOptional<z.ZodString>;
|
|
38
|
+
}, z.core.$strip>;
|
|
39
|
+
};
|
|
40
|
+
export default exportUsersHandler;
|
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
import generateCSVFileAndURL from "./generateCSVFileAndUrl.js";
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { EXPORTS_DIRECTORY } from "../createBulkExporter.js";
|
|
4
|
+
export const UserExportPayloadSchema = z.object({
|
|
5
|
+
exportReviews: z.boolean().optional(),
|
|
6
|
+
exportOrders: z.boolean().optional(),
|
|
7
|
+
exportBookmarks: z.boolean().optional(),
|
|
8
|
+
exportEvents: z.boolean().optional(),
|
|
9
|
+
exportQuotations: z.boolean().optional(),
|
|
10
|
+
exportEnrollments: z.boolean().optional(),
|
|
11
|
+
userId: z.string().optional(),
|
|
12
|
+
});
|
|
13
|
+
const USER_CSV_SCHEMA = {
|
|
14
|
+
userFields: [
|
|
15
|
+
'_id',
|
|
16
|
+
'emailAddresses',
|
|
17
|
+
'tags',
|
|
18
|
+
'roles',
|
|
19
|
+
'username',
|
|
20
|
+
'created',
|
|
21
|
+
'isGuest',
|
|
22
|
+
'displayName',
|
|
23
|
+
'birthday',
|
|
24
|
+
'phoneMobile',
|
|
25
|
+
'gender',
|
|
26
|
+
'address.addressLine',
|
|
27
|
+
'address.addressLine2',
|
|
28
|
+
'address.city',
|
|
29
|
+
'address.company',
|
|
30
|
+
'address.countryCode',
|
|
31
|
+
'address.firstName',
|
|
32
|
+
'address.lastName',
|
|
33
|
+
'address.postalCode',
|
|
34
|
+
'address.regionCode',
|
|
35
|
+
'meta',
|
|
36
|
+
'lastBillingAddress',
|
|
37
|
+
'lastContact',
|
|
38
|
+
'lastLogin',
|
|
39
|
+
],
|
|
40
|
+
bookmarkFields: ['_id', 'productId', 'userId'],
|
|
41
|
+
orderFields: [
|
|
42
|
+
'_id',
|
|
43
|
+
'userId',
|
|
44
|
+
'orderNumber',
|
|
45
|
+
'status',
|
|
46
|
+
'billingAddress',
|
|
47
|
+
'contact',
|
|
48
|
+
'countryCode',
|
|
49
|
+
'currencyCode',
|
|
50
|
+
'deliveryId',
|
|
51
|
+
'paymentId',
|
|
52
|
+
'confirmed',
|
|
53
|
+
'ordered',
|
|
54
|
+
'fulfilled',
|
|
55
|
+
'products',
|
|
56
|
+
],
|
|
57
|
+
reviewFields: [
|
|
58
|
+
'_id',
|
|
59
|
+
'productId',
|
|
60
|
+
'authorId',
|
|
61
|
+
'rating',
|
|
62
|
+
'title',
|
|
63
|
+
'review',
|
|
64
|
+
'vote.type',
|
|
65
|
+
'vote.timestamp',
|
|
66
|
+
'vote.meta',
|
|
67
|
+
'meta',
|
|
68
|
+
],
|
|
69
|
+
quotationFields: [
|
|
70
|
+
'_id',
|
|
71
|
+
'userId',
|
|
72
|
+
'quotationNumber',
|
|
73
|
+
'productId',
|
|
74
|
+
'status',
|
|
75
|
+
'price',
|
|
76
|
+
'expires',
|
|
77
|
+
'fulfilled',
|
|
78
|
+
'rejected',
|
|
79
|
+
'deleted',
|
|
80
|
+
'meta',
|
|
81
|
+
'configuration',
|
|
82
|
+
],
|
|
83
|
+
enrollmentFields: [
|
|
84
|
+
'_id',
|
|
85
|
+
'userId',
|
|
86
|
+
'productId',
|
|
87
|
+
'enrollmentNumber',
|
|
88
|
+
'status',
|
|
89
|
+
'countryCode',
|
|
90
|
+
'currencyCode',
|
|
91
|
+
'quantity',
|
|
92
|
+
'created',
|
|
93
|
+
'deleted',
|
|
94
|
+
'expires',
|
|
95
|
+
'configuration',
|
|
96
|
+
'billingAddress',
|
|
97
|
+
'contact.emailAddress',
|
|
98
|
+
'contact.telNumber',
|
|
99
|
+
'delivery.providerId',
|
|
100
|
+
'payment.providerId',
|
|
101
|
+
'delivery.meta',
|
|
102
|
+
'payment.meta',
|
|
103
|
+
'meta',
|
|
104
|
+
],
|
|
105
|
+
};
|
|
106
|
+
const exportUsersHandler = async ({ userId, ...options }, _, unchainedAPI) => {
|
|
107
|
+
const { modules } = unchainedAPI;
|
|
108
|
+
const user = await modules.users.findUserById(userId);
|
|
109
|
+
const userRows = [];
|
|
110
|
+
const orderRows = [];
|
|
111
|
+
const bookmarkRows = [];
|
|
112
|
+
const quotationRows = [];
|
|
113
|
+
const reviewRows = [];
|
|
114
|
+
const enrollmentRows = [];
|
|
115
|
+
if (!user)
|
|
116
|
+
throw new Error(`User with ID ${userId} not found`);
|
|
117
|
+
userRows.push({
|
|
118
|
+
_id: user._id,
|
|
119
|
+
emailAddresses: user.emails ? user.emails.map((email) => email.address).join('; ') : '',
|
|
120
|
+
created: new Date(user.created).getTime(),
|
|
121
|
+
isGuest: user.guest || false,
|
|
122
|
+
tags: user.tags ? user.tags.join('; ') : '',
|
|
123
|
+
roles: user.roles ? user.roles.join('; ') : '',
|
|
124
|
+
username: user.username || '',
|
|
125
|
+
displayName: user.profile?.displayName || '',
|
|
126
|
+
birthday: user.profile?.birthday ? new Date(user.profile?.birthday).getTime() : '',
|
|
127
|
+
phoneMobile: user.profile?.phoneMobile || '',
|
|
128
|
+
gender: user.profile?.gender || '',
|
|
129
|
+
'address.addressLine': user.profile?.address?.addressLine || '',
|
|
130
|
+
'address.addressLine2': user.profile?.address?.addressLine2 || '',
|
|
131
|
+
'address.city': user.profile?.address?.city || '',
|
|
132
|
+
'address.company': user.profile?.address?.company || '',
|
|
133
|
+
'address.countryCode': user.profile?.address?.countryCode || '',
|
|
134
|
+
'address.firstName': user.profile?.address?.firstName || '',
|
|
135
|
+
'address.lastName': user.profile?.address?.lastName || '',
|
|
136
|
+
'address.postalCode': user.profile?.address?.postalCode || '',
|
|
137
|
+
'address.regionCode': user.profile?.address?.regionCode || '',
|
|
138
|
+
meta: user.meta ? JSON.stringify(user.meta) : '',
|
|
139
|
+
lastBillingAddress: user.lastBillingAddress ? JSON.stringify(user.lastBillingAddress) : '',
|
|
140
|
+
lastContact: user.lastContact ? JSON.stringify(user.lastContact) : '',
|
|
141
|
+
lastLogin: user.lastLogin ? JSON.stringify(user.lastLogin) : '',
|
|
142
|
+
});
|
|
143
|
+
if (options.exportBookmarks) {
|
|
144
|
+
const bookmarks = await modules.bookmarks.findBookmarksByUserId(userId);
|
|
145
|
+
for (const bookmark of bookmarks) {
|
|
146
|
+
const row = {};
|
|
147
|
+
USER_CSV_SCHEMA.bookmarkFields.forEach((field) => {
|
|
148
|
+
row[field] = bookmark[field] || '';
|
|
149
|
+
});
|
|
150
|
+
bookmarkRows.push(row);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if (options.exportOrders) {
|
|
154
|
+
const orders = await modules.orders.findOrders({ userId });
|
|
155
|
+
for await (const order of orders) {
|
|
156
|
+
const positions = await modules.orders.positions.findOrderPositions({ orderId: order._id });
|
|
157
|
+
const row = {};
|
|
158
|
+
USER_CSV_SCHEMA.orderFields.forEach((field) => {
|
|
159
|
+
if ((field === 'ordered' || field === 'confirmed' || field === 'fulfilled') && order[field]) {
|
|
160
|
+
row[field] = new Date(order[field]).getTime();
|
|
161
|
+
}
|
|
162
|
+
else if (field === 'products') {
|
|
163
|
+
row[field] = positions.map((pos) => `${pos.productId}~${pos.quantity}`).join('; ');
|
|
164
|
+
}
|
|
165
|
+
else if (field === 'billingAddress' && order.billingAddress) {
|
|
166
|
+
row[field] = JSON.stringify(order.billingAddress);
|
|
167
|
+
}
|
|
168
|
+
else if (field === 'contact' && order.contact) {
|
|
169
|
+
row[field] = JSON.stringify(order.contact);
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
row[field] = order[field] || '';
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
orderRows.push(row);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (options.exportReviews) {
|
|
179
|
+
const reviews = await modules.products.reviews.findProductReviews({
|
|
180
|
+
authorId: userId,
|
|
181
|
+
});
|
|
182
|
+
for (const review of reviews) {
|
|
183
|
+
const row = {};
|
|
184
|
+
USER_CSV_SCHEMA.reviewFields.forEach((field) => {
|
|
185
|
+
if (field.startsWith('vote.')) {
|
|
186
|
+
const voteField = field.split('.')[1];
|
|
187
|
+
if (voteField === 'timestamp' && review.votes[0][voteField]) {
|
|
188
|
+
row[field] = new Date(review.votes[0][voteField]).getTime();
|
|
189
|
+
}
|
|
190
|
+
else if (voteField === 'meta' && review.votes[0][voteField]) {
|
|
191
|
+
row[field] = JSON.stringify(review.votes[0][voteField]);
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
row[field] = review.votes[0][voteField] || '';
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
if (field === 'meta' && review.meta) {
|
|
199
|
+
row[field] = JSON.stringify(review.meta);
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
row[field] = review[field] || '';
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
reviewRows.push(row);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
if (options.exportQuotations) {
|
|
210
|
+
const quotations = await modules.quotations.findQuotations({
|
|
211
|
+
userId,
|
|
212
|
+
});
|
|
213
|
+
for (const quotation of quotations) {
|
|
214
|
+
const row = {};
|
|
215
|
+
USER_CSV_SCHEMA.quotationFields.forEach((field) => {
|
|
216
|
+
if ((field === 'expires' ||
|
|
217
|
+
field === 'fulfilled' ||
|
|
218
|
+
field === 'rejected' ||
|
|
219
|
+
field === 'deleted') &&
|
|
220
|
+
quotation[field]) {
|
|
221
|
+
row[field] = new Date(quotation[field]).getTime();
|
|
222
|
+
}
|
|
223
|
+
else if (field === 'configuration' || (field === 'meta' && quotation[field])) {
|
|
224
|
+
row[field] = JSON.stringify(quotation.configuration);
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
row[field] = quotation[field] || '';
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
quotationRows.push(row);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
if (options.exportEnrollments) {
|
|
234
|
+
const enrollments = await modules.enrollments.findEnrollments({
|
|
235
|
+
userId,
|
|
236
|
+
});
|
|
237
|
+
for (const enrollment of enrollments) {
|
|
238
|
+
const row = {};
|
|
239
|
+
USER_CSV_SCHEMA.enrollmentFields.forEach((field) => {
|
|
240
|
+
if ((field === 'created' || field === 'deleted' || field === 'expires') && enrollment[field]) {
|
|
241
|
+
row[field] = new Date(enrollment[field]).getTime();
|
|
242
|
+
}
|
|
243
|
+
else if (field === 'billingAddress' && enrollment[field]) {
|
|
244
|
+
row[field] = JSON.stringify(enrollment[field]);
|
|
245
|
+
}
|
|
246
|
+
else if (field === 'contact.emailAddress' && enrollment.contact) {
|
|
247
|
+
row[field] = enrollment.contact.emailAddress || '';
|
|
248
|
+
}
|
|
249
|
+
else if (field === 'contact.telNumber' && enrollment.contact) {
|
|
250
|
+
row[field] = enrollment.contact.telNumber || '';
|
|
251
|
+
}
|
|
252
|
+
else if (field === 'delivery.providerId' && enrollment.delivery) {
|
|
253
|
+
row[field] = enrollment.delivery.deliveryProviderId || '';
|
|
254
|
+
}
|
|
255
|
+
else if (field === 'payment.providerId' && enrollment.payment) {
|
|
256
|
+
row[field] = enrollment.payment.paymentProviderId || '';
|
|
257
|
+
}
|
|
258
|
+
else if (field === 'delivery.meta' && enrollment.delivery) {
|
|
259
|
+
row[field] = enrollment.delivery.meta
|
|
260
|
+
? JSON.stringify(enrollment.delivery.meta)
|
|
261
|
+
: '';
|
|
262
|
+
}
|
|
263
|
+
else if (field === 'payment.meta' && enrollment.payment) {
|
|
264
|
+
row[field] = enrollment.payment.meta
|
|
265
|
+
? JSON.stringify(enrollment.payment.meta)
|
|
266
|
+
: '';
|
|
267
|
+
}
|
|
268
|
+
else if (field === 'configuration' || (field === 'meta' && enrollment[field])) {
|
|
269
|
+
row[field] = JSON.stringify(enrollment.configuration);
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
row[field] = enrollment[field] || '';
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
enrollmentRows.push(row);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
const userCSV = await generateCSVFileAndURL({
|
|
279
|
+
headers: USER_CSV_SCHEMA.userFields,
|
|
280
|
+
rows: userRows,
|
|
281
|
+
directoryName: EXPORTS_DIRECTORY,
|
|
282
|
+
fileName: 'user_export.csv',
|
|
283
|
+
unchainedAPI,
|
|
284
|
+
});
|
|
285
|
+
const reviewCSV = options.exportReviews
|
|
286
|
+
? await generateCSVFileAndURL({
|
|
287
|
+
headers: USER_CSV_SCHEMA.reviewFields,
|
|
288
|
+
rows: reviewRows,
|
|
289
|
+
directoryName: EXPORTS_DIRECTORY,
|
|
290
|
+
fileName: 'user_reviews_export.csv',
|
|
291
|
+
unchainedAPI,
|
|
292
|
+
})
|
|
293
|
+
: null;
|
|
294
|
+
const quotationCSV = options.exportQuotations
|
|
295
|
+
? await generateCSVFileAndURL({
|
|
296
|
+
headers: USER_CSV_SCHEMA.quotationFields,
|
|
297
|
+
rows: quotationRows,
|
|
298
|
+
directoryName: EXPORTS_DIRECTORY,
|
|
299
|
+
fileName: 'user_quotations_export.csv',
|
|
300
|
+
unchainedAPI,
|
|
301
|
+
})
|
|
302
|
+
: null;
|
|
303
|
+
const bookmarksCSV = options.exportBookmarks
|
|
304
|
+
? await generateCSVFileAndURL({
|
|
305
|
+
headers: USER_CSV_SCHEMA.bookmarkFields,
|
|
306
|
+
rows: bookmarkRows,
|
|
307
|
+
directoryName: EXPORTS_DIRECTORY,
|
|
308
|
+
fileName: 'user_bookmarks_export.csv',
|
|
309
|
+
unchainedAPI,
|
|
310
|
+
})
|
|
311
|
+
: null;
|
|
312
|
+
const ordersCSV = options.exportOrders
|
|
313
|
+
? await generateCSVFileAndURL({
|
|
314
|
+
headers: USER_CSV_SCHEMA.orderFields,
|
|
315
|
+
rows: orderRows,
|
|
316
|
+
directoryName: EXPORTS_DIRECTORY,
|
|
317
|
+
fileName: 'user_orders_export.csv',
|
|
318
|
+
unchainedAPI,
|
|
319
|
+
})
|
|
320
|
+
: null;
|
|
321
|
+
const enrollmentCSV = options.exportEnrollments
|
|
322
|
+
? await generateCSVFileAndURL({
|
|
323
|
+
headers: USER_CSV_SCHEMA.enrollmentFields,
|
|
324
|
+
rows: enrollmentRows,
|
|
325
|
+
directoryName: EXPORTS_DIRECTORY,
|
|
326
|
+
fileName: 'user_enrollments_export.csv',
|
|
327
|
+
unchainedAPI,
|
|
328
|
+
})
|
|
329
|
+
: null;
|
|
330
|
+
return {
|
|
331
|
+
user: userCSV,
|
|
332
|
+
bookmarks: bookmarksCSV,
|
|
333
|
+
orders: ordersCSV,
|
|
334
|
+
reviews: reviewCSV,
|
|
335
|
+
quotations: quotationCSV,
|
|
336
|
+
enrollments: enrollmentCSV,
|
|
337
|
+
};
|
|
338
|
+
};
|
|
339
|
+
export default exportUsersHandler;
|
|
340
|
+
exportUsersHandler.payloadSchema = UserExportPayloadSchema;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { UnchainedCore } from '../../core-index.ts';
|
|
2
|
+
export interface CSVFileResult {
|
|
3
|
+
url: string;
|
|
4
|
+
expires: number;
|
|
5
|
+
}
|
|
6
|
+
declare const generateCSVFileAndURL: ({ rows, headers, directoryName, fileName, unchainedAPI, }: {
|
|
7
|
+
rows: Record<string, unknown>[];
|
|
8
|
+
headers: string[];
|
|
9
|
+
directoryName: string;
|
|
10
|
+
fileName: string;
|
|
11
|
+
unchainedAPI: UnchainedCore;
|
|
12
|
+
}, expires?: number) => Promise<CSVFileResult>;
|
|
13
|
+
export default generateCSVFileAndURL;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import toCSV from "./toCSV.js";
|
|
2
|
+
const generateCSVFileAndURL = async ({ rows, headers, directoryName, fileName, unchainedAPI, }, expires = 3600000) => {
|
|
3
|
+
if (!rows.length)
|
|
4
|
+
return { url: '', expires: 0 };
|
|
5
|
+
const csvString = toCSV(headers, rows);
|
|
6
|
+
const uploaded = await unchainedAPI.services.files.uploadFileFromStream({
|
|
7
|
+
directoryName,
|
|
8
|
+
rawFile: { filename: fileName, buffer: Buffer.from(csvString).toString('base64') },
|
|
9
|
+
meta: { isPrivate: true },
|
|
10
|
+
});
|
|
11
|
+
const expiresAt = Date.now() + expires;
|
|
12
|
+
const url = await unchainedAPI.services.files.createFileDownloadURL({
|
|
13
|
+
file: uploaded,
|
|
14
|
+
expires: expiresAt,
|
|
15
|
+
});
|
|
16
|
+
if (!url) {
|
|
17
|
+
throw new Error(`Failed to generate download URL for ${fileName}`);
|
|
18
|
+
}
|
|
19
|
+
return { url, expires: expiresAt };
|
|
20
|
+
};
|
|
21
|
+
export default generateCSVFileAndURL;
|
|
@@ -5,7 +5,6 @@ export declare const AssortmentCreatePayloadSchema: z.ZodObject<{
|
|
|
5
5
|
_id: z.ZodString;
|
|
6
6
|
specification: z.ZodObject<{
|
|
7
7
|
isActive: z.ZodBoolean;
|
|
8
|
-
isBase: z.ZodOptional<z.ZodBoolean>;
|
|
9
8
|
isRoot: z.ZodOptional<z.ZodBoolean>;
|
|
10
9
|
sequence: z.ZodNumber;
|
|
11
10
|
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
@@ -71,7 +70,6 @@ declare namespace createAssortment {
|
|
|
71
70
|
_id: z.ZodString;
|
|
72
71
|
specification: z.ZodObject<{
|
|
73
72
|
isActive: z.ZodBoolean;
|
|
74
|
-
isBase: z.ZodOptional<z.ZodBoolean>;
|
|
75
73
|
isRoot: z.ZodOptional<z.ZodBoolean>;
|
|
76
74
|
sequence: z.ZodNumber;
|
|
77
75
|
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
@@ -5,7 +5,6 @@ export declare const AssortmentUpdatePayloadSchema: z.ZodObject<{
|
|
|
5
5
|
_id: z.ZodString;
|
|
6
6
|
specification: z.ZodOptional<z.ZodObject<{
|
|
7
7
|
isActive: z.ZodOptional<z.ZodBoolean>;
|
|
8
|
-
isBase: z.ZodOptional<z.ZodBoolean>;
|
|
9
8
|
isRoot: z.ZodOptional<z.ZodBoolean>;
|
|
10
9
|
sequence: z.ZodOptional<z.ZodNumber>;
|
|
11
10
|
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
@@ -72,7 +71,6 @@ declare namespace updateAssortment {
|
|
|
72
71
|
_id: z.ZodString;
|
|
73
72
|
specification: z.ZodOptional<z.ZodObject<{
|
|
74
73
|
isActive: z.ZodOptional<z.ZodBoolean>;
|
|
75
|
-
isBase: z.ZodOptional<z.ZodBoolean>;
|
|
76
74
|
isRoot: z.ZodOptional<z.ZodBoolean>;
|
|
77
75
|
sequence: z.ZodOptional<z.ZodNumber>;
|
|
78
76
|
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
@@ -10,7 +10,6 @@ export const AssortmentUpdatePayloadSchema = z.object({
|
|
|
10
10
|
specification: z
|
|
11
11
|
.object({
|
|
12
12
|
isActive: z.boolean().optional(),
|
|
13
|
-
isBase: z.boolean().optional(),
|
|
14
13
|
isRoot: z.boolean().optional(),
|
|
15
14
|
sequence: z.number().optional(),
|
|
16
15
|
tags: z.array(z.string()).optional(),
|
|
@@ -17,8 +17,8 @@ export const ProductCreateSpecificationSchema = z.object({
|
|
|
17
17
|
maxQuantity: z.number().optional(),
|
|
18
18
|
isTaxable: z.boolean().optional(),
|
|
19
19
|
isNetPrice: z.boolean().optional(),
|
|
20
|
-
currencyCode: z.string(),
|
|
21
|
-
countryCode: z.string(),
|
|
20
|
+
currencyCode: z.string().min(1, 'currencyCode is required'),
|
|
21
|
+
countryCode: z.string().min(1, 'countryCode is required'),
|
|
22
22
|
})),
|
|
23
23
|
})
|
|
24
24
|
.optional(),
|
|
@@ -16,8 +16,8 @@ export const ProductUpdateSpecificationSchema = z.object({
|
|
|
16
16
|
maxQuantity: z.number().optional(),
|
|
17
17
|
isTaxable: z.boolean().optional(),
|
|
18
18
|
isNetPrice: z.boolean().optional(),
|
|
19
|
-
currencyCode: z.string(),
|
|
20
|
-
countryCode: z.string(),
|
|
19
|
+
currencyCode: z.string().min(1, 'currencyCode is required'),
|
|
20
|
+
countryCode: z.string().min(1, 'countryCode is required'),
|
|
21
21
|
})),
|
|
22
22
|
})
|
|
23
23
|
.optional(),
|
package/lib/core-index.d.ts
CHANGED
|
@@ -3,10 +3,12 @@ import { type CustomServices, type Services } from './services/index.ts';
|
|
|
3
3
|
import { type Modules, type ModuleOptions } from './modules.ts';
|
|
4
4
|
import { type BulkImporter, type BulkImportHandler } from './bulk-importer/index.ts';
|
|
5
5
|
import type { IBaseAdapter } from '@unchainedshop/utils';
|
|
6
|
+
import { type BulkExporter, type BulkExportHandler } from './bulk-exporter/index.ts';
|
|
6
7
|
export * from './bulk-importer/index.ts';
|
|
7
8
|
export * from './services/index.ts';
|
|
8
9
|
export * from './directors/index.ts';
|
|
9
10
|
export * from './factory/index.ts';
|
|
11
|
+
export * from './bulk-exporter/index.ts';
|
|
10
12
|
export { default as schedule, type ScheduleData } from './utils/schedule.ts';
|
|
11
13
|
export interface UnchainedCoreOptions {
|
|
12
14
|
db: mongodb.Db;
|
|
@@ -14,6 +16,9 @@ export interface UnchainedCoreOptions {
|
|
|
14
16
|
bulkImporter?: {
|
|
15
17
|
handlers?: Record<string, BulkImportHandler<UnchainedCore>>;
|
|
16
18
|
};
|
|
19
|
+
bulkExporter?: {
|
|
20
|
+
handlers?: Record<string, BulkExportHandler<UnchainedCore>>;
|
|
21
|
+
};
|
|
17
22
|
modules?: Record<string, {
|
|
18
23
|
configure: (params: ModuleInput<any>) => any;
|
|
19
24
|
}>;
|
|
@@ -25,6 +30,7 @@ export interface UnchainedCore {
|
|
|
25
30
|
services: Services;
|
|
26
31
|
bulkImporter: BulkImporter;
|
|
27
32
|
options: ModuleOptions;
|
|
33
|
+
bulkExporter: BulkExporter;
|
|
28
34
|
}
|
|
29
|
-
export declare const initCore: ({ db, migrationRepository, bulkImporter: bulkImporterOptions, modules: customModules, services: customServices, options, }: UnchainedCoreOptions) => Promise<UnchainedCore>;
|
|
35
|
+
export declare const initCore: ({ db, migrationRepository, bulkImporter: bulkImporterOptions, modules: customModules, services: customServices, options, bulkExporter: bulkExporterOptions, }: UnchainedCoreOptions) => Promise<UnchainedCore>;
|
|
30
36
|
export declare const getAllAdapters: () => IBaseAdapter[];
|
package/lib/core-index.js
CHANGED
|
@@ -3,13 +3,16 @@ import initServices, {} from "./services/index.js";
|
|
|
3
3
|
import initModules, {} from "./modules.js";
|
|
4
4
|
import createBulkImporterFactory, {} from "./bulk-importer/index.js";
|
|
5
5
|
import { WorkerDirector, DeliveryDirector, DeliveryPricingDirector, EnrollmentDirector, FilterDirector, OrderDiscountDirector, OrderPricingDirector, PaymentDirector, PaymentPricingDirector, ProductDiscountDirector, ProductPricingDirector, QuotationDirector, WarehousingDirector, } from "./directors/index.js";
|
|
6
|
+
import createBulkExporterFactory, {} from "./bulk-exporter/index.js";
|
|
6
7
|
export * from "./bulk-importer/index.js";
|
|
7
8
|
export * from "./services/index.js";
|
|
8
9
|
export * from "./directors/index.js";
|
|
9
10
|
export * from "./factory/index.js";
|
|
11
|
+
export * from "./bulk-exporter/index.js";
|
|
10
12
|
export { default as schedule } from "./utils/schedule.js";
|
|
11
|
-
export const initCore = async ({ db, migrationRepository, bulkImporter: bulkImporterOptions = {}, modules: customModules = {}, services: customServices = {}, options = {}, }) => {
|
|
13
|
+
export const initCore = async ({ db, migrationRepository, bulkImporter: bulkImporterOptions = {}, modules: customModules = {}, services: customServices = {}, options = {}, bulkExporter: bulkExporterOptions = {}, }) => {
|
|
12
14
|
const bulkImporter = createBulkImporterFactory(db, bulkImporterOptions);
|
|
15
|
+
const bulkExporter = createBulkExporterFactory(bulkExporterOptions);
|
|
13
16
|
const modules = await initModules({ db, migrationRepository, options }, customModules);
|
|
14
17
|
const services = initServices(modules, customServices);
|
|
15
18
|
return {
|
|
@@ -17,6 +20,7 @@ export const initCore = async ({ db, migrationRepository, bulkImporter: bulkImpo
|
|
|
17
20
|
services,
|
|
18
21
|
bulkImporter,
|
|
19
22
|
options,
|
|
23
|
+
bulkExporter,
|
|
20
24
|
};
|
|
21
25
|
};
|
|
22
26
|
export const getAllAdapters = () => {
|
|
@@ -3,11 +3,14 @@ import type { EnrollmentAdapterActions, EnrollmentContext, IEnrollmentAdapter }
|
|
|
3
3
|
import type { OrderPosition } from '@unchainedshop/core-orders';
|
|
4
4
|
import type { Product } from '@unchainedshop/core-products';
|
|
5
5
|
import type { Enrollment } from '@unchainedshop/core-enrollments';
|
|
6
|
+
import type { Modules } from '../modules.ts';
|
|
6
7
|
export type IEnrollmentDirector = IBaseDirector<IEnrollmentAdapter> & {
|
|
7
8
|
transformOrderItemToEnrollment: (item: {
|
|
8
9
|
orderPosition: OrderPosition;
|
|
9
10
|
product: Product;
|
|
10
11
|
}, doc: Omit<Enrollment, 'configuration' | 'productId' | 'quantity' | 'status' | 'periods' | 'log' | '_id' | 'created'>, unchainedAPI: any) => Promise<Omit<Enrollment, 'status' | 'periods' | 'log' | '_id' | 'created'> & Pick<Partial<Enrollment>, '_id' | 'created'>>;
|
|
11
|
-
actions: (enrollmentContext: EnrollmentContext, unchainedAPI:
|
|
12
|
+
actions: (enrollmentContext: EnrollmentContext, unchainedAPI: {
|
|
13
|
+
modules: Modules;
|
|
14
|
+
}) => Promise<EnrollmentAdapterActions>;
|
|
12
15
|
};
|
|
13
16
|
export declare const EnrollmentDirector: IEnrollmentDirector;
|
|
@@ -150,6 +150,8 @@ export const PaymentDirector = {
|
|
|
150
150
|
const paymentProvider = await modules.payment.paymentProviders.findProvider({
|
|
151
151
|
paymentProviderId: orderPayment.paymentProviderId,
|
|
152
152
|
});
|
|
153
|
+
if (!paymentProvider)
|
|
154
|
+
throw new Error('Payment provider not found: ' + orderPayment.paymentProviderId);
|
|
153
155
|
const actions = await PaymentDirector.actions(paymentProvider, buildPaymentProviderActionsContext(orderPayment, {
|
|
154
156
|
...context,
|
|
155
157
|
transactionContext: {
|
|
@@ -3,6 +3,7 @@ import type { WorkResult } from '@unchainedshop/core-worker';
|
|
|
3
3
|
import type { ModuleOptions, Modules } from '../modules.ts';
|
|
4
4
|
import type { Services } from '../services/index.ts';
|
|
5
5
|
import type { BulkImporter } from '../bulk-importer/index.ts';
|
|
6
|
+
import type { BulkExporter } from '../bulk-exporter/index.ts';
|
|
6
7
|
export type IWorkerAdapter<Input, Output> = IBaseAdapter & {
|
|
7
8
|
type: string;
|
|
8
9
|
external: boolean;
|
|
@@ -12,6 +13,7 @@ export type IWorkerAdapter<Input, Output> = IBaseAdapter & {
|
|
|
12
13
|
services: Services;
|
|
13
14
|
bulkImporter: BulkImporter;
|
|
14
15
|
options: ModuleOptions;
|
|
16
|
+
bulkExporter: BulkExporter;
|
|
15
17
|
}, workId: string) => Promise<WorkResult<Output>>;
|
|
16
18
|
};
|
|
17
19
|
export declare const WorkerAdapter: Omit<IWorkerAdapter<any, void>, 'key' | 'label' | 'type' | 'version'>;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { QuotationStatus } from '@unchainedshop/core-quotations';
|
|
2
2
|
import { processQuotationService } from "./processQuotation.js";
|
|
3
|
-
export async function
|
|
4
|
-
if (quotation.status === QuotationStatus.
|
|
3
|
+
export async function fulfillQuotationService(quotation, info) {
|
|
4
|
+
if (quotation.status === QuotationStatus.FULFILLED)
|
|
5
5
|
return quotation;
|
|
6
6
|
const updatedQuotation = await this.quotations.updateStatus(quotation._id, {
|
|
7
|
-
status: QuotationStatus.
|
|
7
|
+
status: QuotationStatus.FULFILLED,
|
|
8
8
|
info: JSON.stringify(info),
|
|
9
9
|
});
|
|
10
10
|
return processQuotationService.bind(this)(updatedQuotation, {});
|
package/lib/services/index.d.ts
CHANGED
|
@@ -32,7 +32,7 @@ import { initializeEnrollmentService } from './initializeEnrollment.ts';
|
|
|
32
32
|
import { activateEnrollmentService } from './activateEnrollment.ts';
|
|
33
33
|
import { terminateEnrollmentService } from './terminateEnrollment.ts';
|
|
34
34
|
import { invalidateFilterCacheService } from './invalidateFilterCache.ts';
|
|
35
|
-
import {
|
|
35
|
+
import { fulfillQuotationService } from './fulfillQuotation.ts';
|
|
36
36
|
import { processQuotationService } from './processQuotation.ts';
|
|
37
37
|
import { proposeQuotationService } from './proposeQuotation.ts';
|
|
38
38
|
import { rejectQuotationService } from './rejectQuotation.ts';
|
|
@@ -116,7 +116,7 @@ export default function initServices(modules: Modules, customServices?: CustomSe
|
|
|
116
116
|
terminateEnrollment: Bound<typeof terminateEnrollmentService>;
|
|
117
117
|
};
|
|
118
118
|
quotations: {
|
|
119
|
-
|
|
119
|
+
fulfillQuotation: Bound<typeof fulfillQuotationService>;
|
|
120
120
|
processQuotation: Bound<typeof processQuotationService>;
|
|
121
121
|
proposeQuotation: Bound<typeof proposeQuotationService>;
|
|
122
122
|
rejectQuotation: Bound<typeof rejectQuotationService>;
|