@devx-commerce/plugin-gati 0.0.34-beta.9 → 0.0.35-beta.2
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/.medusa/server/development/erp-order-payload-example.js +76 -0
- package/.medusa/server/src/api/admin/variant-options/recalculate/route.js +446 -0
- package/.medusa/server/src/api/admin/variant-options/sync/route.js +21 -5
- package/.medusa/server/src/api/erp/webhook/config.js +6 -1
- package/.medusa/server/src/api/erp/webhook/route.js +10 -137
- package/.medusa/server/src/jobs/process-erp-events.js +205 -0
- package/.medusa/server/src/jobs/process-variant-option-sync.js +43 -28
- package/.medusa/server/src/subscribers/cutomer-updated.js +3 -1
- package/.medusa/server/src/subscribers/party-master.js +36 -35
- package/.medusa/server/src/workflows/helpers/product-helper.js +33 -17
- package/.medusa/server/src/workflows/helpers/variant-helper.js +165 -162
- package/.medusa/server/src/workflows/hooks/product-updated.js +6 -11
- package/.medusa/server/src/workflows/inward-master/workflows/update-inward.js +6 -2
- package/.medusa/server/src/workflows/party-master/steps/fetch-party-master.js +2 -1
- package/.medusa/server/src/workflows/party-master/workflows/create-or-update-party-master.js +2 -2
- package/.medusa/server/src/workflows/party-style-master/steps/update-product-options-after-deletion.js +16 -249
- package/.medusa/server/src/workflows/party-style-master/steps/update-product-options-after-variant-update.js +103 -22
- package/.medusa/server/src/workflows/party-style-master/workflows/create-or-update-party-style-master.js +16 -10
- package/.medusa/server/src/workflows/style-master/workflows/create-or-update-style-master.js +2 -2
- package/.medusa/server/src/workflows/update-extended-product-from-product/index.js +6 -8
- package/.medusa/server/src/workflows/update-extended-variant-from-variant/workflows/update-extended-variant-status-from-variant.js +9 -3
- package/package.json +1 -1
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const orderPayload = {
|
|
4
|
+
OrderId: 0,
|
|
5
|
+
BranchNo: "0004000711",
|
|
6
|
+
BranchName: "Timeless Jewels",
|
|
7
|
+
OrderPrefix: "",
|
|
8
|
+
OrderNo: "",
|
|
9
|
+
OrderDate: "2025-06-21T00:00:00",
|
|
10
|
+
CustomerId: "0001000056",
|
|
11
|
+
Customer: "",
|
|
12
|
+
PoNo: "ID1111",
|
|
13
|
+
PoDate: "2025-06-21T00:00:00",
|
|
14
|
+
SalesPerson: "",
|
|
15
|
+
WorkOrderNo: "",
|
|
16
|
+
Remarks: "",
|
|
17
|
+
PromocodeSeriesId: 0,
|
|
18
|
+
Promocode: "",
|
|
19
|
+
PromocodePercentage: 0,
|
|
20
|
+
PromocodeAmount: 0,
|
|
21
|
+
OrderDetail: [
|
|
22
|
+
{
|
|
23
|
+
OrderId: 0,
|
|
24
|
+
OrderItemId: 0,
|
|
25
|
+
SrNo: 1,
|
|
26
|
+
StyleId: 33067,
|
|
27
|
+
StyleCode: "DR00962",
|
|
28
|
+
PartyStyleId: 5445,
|
|
29
|
+
PartyStyleCode: "DR00260",
|
|
30
|
+
JewelId: 0,
|
|
31
|
+
JewelCode: "",
|
|
32
|
+
ItemSize: "5",
|
|
33
|
+
OrderQty: 1.0,
|
|
34
|
+
OrderItemPcs: 1,
|
|
35
|
+
Metal: "",
|
|
36
|
+
Tone: "",
|
|
37
|
+
ItemPoNo: "",
|
|
38
|
+
ItemRefNo: "",
|
|
39
|
+
Priority: "N",
|
|
40
|
+
StockType: "LG DIAMOND",
|
|
41
|
+
MakeType: "A",
|
|
42
|
+
CustomerProductionInstruction: "",
|
|
43
|
+
SpecialRemarks: "",
|
|
44
|
+
DesignProductionInstruction: "",
|
|
45
|
+
StampInstruction: "",
|
|
46
|
+
Expecteddeliverydate: "2025-06-25T00:00:00",
|
|
47
|
+
MRP: 36063.0,
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
PaymentOption: [
|
|
51
|
+
{
|
|
52
|
+
OrderId: 0,
|
|
53
|
+
BookName: "UPI TimeLess - P",
|
|
54
|
+
Amount: 37144.89,
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
};
|
|
58
|
+
console.log(JSON.stringify(orderPayload, null, 2));
|
|
59
|
+
// You can use this payload with the ErpService.createOrder method.
|
|
60
|
+
// Example:
|
|
61
|
+
// import ErpService from './src/modules/erp/service';
|
|
62
|
+
// const erpService = new ErpService(
|
|
63
|
+
// {},
|
|
64
|
+
// {
|
|
65
|
+
// authToken: "D7F0A5C3-E229-4BBF-AA62-5D8B858EB887",
|
|
66
|
+
// baseUrl: "http://103.98.6.30:90/api/Svaraa",
|
|
67
|
+
// }
|
|
68
|
+
// );
|
|
69
|
+
// erpService.createOrder(orderPayload)
|
|
70
|
+
// .then(result => {
|
|
71
|
+
// console.log('Order created successfully:', result);
|
|
72
|
+
// })
|
|
73
|
+
// .catch(error => {
|
|
74
|
+
// console.error('Error creating order:', error);
|
|
75
|
+
// });
|
|
76
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJwLW9yZGVyLXBheWxvYWQtZXhhbXBsZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2RldmVsb3BtZW50L2VycC1vcmRlci1wYXlsb2FkLWV4YW1wbGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFFQSxNQUFNLFlBQVksR0FBaUI7SUFDakMsT0FBTyxFQUFFLENBQUM7SUFDVixRQUFRLEVBQUUsWUFBWTtJQUN0QixVQUFVLEVBQUUsaUJBQWlCO0lBQzdCLFdBQVcsRUFBRSxFQUFFO0lBQ2YsT0FBTyxFQUFFLEVBQUU7SUFDWCxTQUFTLEVBQUUscUJBQXFCO0lBQ2hDLFVBQVUsRUFBRSxZQUFZO0lBQ3hCLFFBQVEsRUFBRSxFQUFFO0lBQ1osSUFBSSxFQUFFLFFBQVE7SUFDZCxNQUFNLEVBQUUscUJBQXFCO0lBQzdCLFdBQVcsRUFBRSxFQUFFO0lBQ2YsV0FBVyxFQUFFLEVBQUU7SUFDZixPQUFPLEVBQUUsRUFBRTtJQUNYLGlCQUFpQixFQUFFLENBQUM7SUFDcEIsU0FBUyxFQUFFLEVBQUU7SUFDYixtQkFBbUIsRUFBRSxDQUFDO0lBQ3RCLGVBQWUsRUFBRSxDQUFDO0lBQ2xCLFdBQVcsRUFBRTtRQUNYO1lBQ0UsT0FBTyxFQUFFLENBQUM7WUFDVixXQUFXLEVBQUUsQ0FBQztZQUNkLElBQUksRUFBRSxDQUFDO1lBQ1AsT0FBTyxFQUFFLEtBQUs7WUFDZCxTQUFTLEVBQUUsU0FBUztZQUNwQixZQUFZLEVBQUUsSUFBSTtZQUNsQixjQUFjLEVBQUUsU0FBUztZQUN6QixPQUFPLEVBQUUsQ0FBQztZQUNWLFNBQVMsRUFBRSxFQUFFO1lBQ2IsUUFBUSxFQUFFLEdBQUc7WUFDYixRQUFRLEVBQUUsR0FBRztZQUNiLFlBQVksRUFBRSxDQUFDO1lBQ2YsS0FBSyxFQUFFLEVBQUU7WUFDVCxJQUFJLEVBQUUsRUFBRTtZQUNSLFFBQVEsRUFBRSxFQUFFO1lBQ1osU0FBUyxFQUFFLEVBQUU7WUFDYixRQUFRLEVBQUUsR0FBRztZQUNiLFNBQVMsRUFBRSxZQUFZO1lBQ3ZCLFFBQVEsRUFBRSxHQUFHO1lBQ2IsNkJBQTZCLEVBQUUsRUFBRTtZQUNqQyxjQUFjLEVBQUUsRUFBRTtZQUNsQiwyQkFBMkIsRUFBRSxFQUFFO1lBQy9CLGdCQUFnQixFQUFFLEVBQUU7WUFDcEIsb0JBQW9CLEVBQUUscUJBQXFCO1lBQzNDLEdBQUcsRUFBRSxPQUFPO1NBQ2I7S0FDRjtJQUNELGFBQWEsRUFBRTtRQUNiO1lBQ0UsT0FBTyxFQUFFLENBQUM7WUFDVixRQUFRLEVBQUUsa0JBQWtCO1lBQzVCLE1BQU0sRUFBRSxRQUFRO1NBQ2pCO0tBQ0Y7Q0FDRixDQUFDO0FBRUYsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLFlBQVksRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUVuRCxtRUFBbUU7QUFDbkUsV0FBVztBQUVYLHNEQUFzRDtBQUV0RCxxQ0FBcUM7QUFDckMsUUFBUTtBQUNSLE1BQU07QUFDTix5REFBeUQ7QUFDekQsbURBQW1EO0FBQ25ELE1BQU07QUFDTixLQUFLO0FBRUwsdUNBQXVDO0FBQ3ZDLHNCQUFzQjtBQUN0QiwwREFBMEQ7QUFDMUQsT0FBTztBQUNQLHNCQUFzQjtBQUN0QixxREFBcUQ7QUFDckQsUUFBUSJ9
|
|
@@ -0,0 +1,446 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.POST = void 0;
|
|
4
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
5
|
+
const core_flows_1 = require("@medusajs/medusa/core-flows");
|
|
6
|
+
const api_response_1 = require("../../../../lib/api-response");
|
|
7
|
+
const update_variant_option_metadata_1 = require("../../../../workflows/helpers/update-variant-option-metadata");
|
|
8
|
+
const BATCH_SIZE = 10; // Process 10 products at a time
|
|
9
|
+
/**
|
|
10
|
+
* POST /admin/variant-options/recalculate
|
|
11
|
+
*
|
|
12
|
+
* Recalculate product options for one or more products and all their variants.
|
|
13
|
+
* This is useful when:
|
|
14
|
+
* - Options got out of sync
|
|
15
|
+
* - After bulk updates
|
|
16
|
+
* - To fix option mismatch errors
|
|
17
|
+
*
|
|
18
|
+
* Body:
|
|
19
|
+
* { style_id: string } - Single style
|
|
20
|
+
* { style_ids: string[] } - Multiple styles (processed in batches)
|
|
21
|
+
* { product_id: string } - Single product
|
|
22
|
+
* { product_ids: string[] } - Multiple products (processed in batches)
|
|
23
|
+
*/
|
|
24
|
+
const POST = async (req, res) => {
|
|
25
|
+
const query = req.scope.resolve(utils_1.ContainerRegistrationKeys.QUERY);
|
|
26
|
+
const logger = req.scope.resolve(utils_1.ContainerRegistrationKeys.LOGGER);
|
|
27
|
+
const { style_id, style_ids, product_id, product_ids } = (req.body || {});
|
|
28
|
+
// Normalize inputs to arrays
|
|
29
|
+
const styleIdList = style_ids || (style_id ? [style_id] : []);
|
|
30
|
+
const productIdList = product_ids || (product_id ? [product_id] : []);
|
|
31
|
+
if (styleIdList.length === 0 && productIdList.length === 0) {
|
|
32
|
+
return (0, api_response_1.sendApiResponse)(res, (0, api_response_1.createErrorResponse)("Provide style_id, style_ids, product_id, or product_ids", api_response_1.HttpStatus.BAD_REQUEST, api_response_1.ErrorCode.VALIDATION_ERROR));
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
const totalItems = styleIdList.length + productIdList.length;
|
|
36
|
+
logger.info(`[recalculate-options] Starting for ${totalItems} item(s)`);
|
|
37
|
+
// Load master maps once - shared across all products
|
|
38
|
+
const masterMaps = await loadMasterMaps(query);
|
|
39
|
+
// Collect all products to process
|
|
40
|
+
const productsToProcess = [];
|
|
41
|
+
// Fetch products by style_ids
|
|
42
|
+
if (styleIdList.length > 0) {
|
|
43
|
+
const { data: productsByStyle } = await query.graph({
|
|
44
|
+
entity: "product",
|
|
45
|
+
fields: ["id", "external_id", "options.*"],
|
|
46
|
+
filters: {
|
|
47
|
+
external_id: styleIdList,
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
productsToProcess.push(...(productsByStyle || []));
|
|
51
|
+
}
|
|
52
|
+
// Fetch products by product_ids
|
|
53
|
+
if (productIdList.length > 0) {
|
|
54
|
+
const { data: productsById } = await query.graph({
|
|
55
|
+
entity: "product",
|
|
56
|
+
fields: ["id", "external_id", "options.*"],
|
|
57
|
+
filters: {
|
|
58
|
+
id: productIdList,
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
productsToProcess.push(...(productsById || []));
|
|
62
|
+
}
|
|
63
|
+
// Deduplicate by product id
|
|
64
|
+
const uniqueProducts = Array.from(new Map(productsToProcess.map(p => [p.id, p])).values());
|
|
65
|
+
if (uniqueProducts.length === 0) {
|
|
66
|
+
return (0, api_response_1.sendApiResponse)(res, (0, api_response_1.createErrorResponse)("No products found for the provided identifiers", api_response_1.HttpStatus.NOT_FOUND, api_response_1.ErrorCode.NOT_FOUND));
|
|
67
|
+
}
|
|
68
|
+
logger.info(`[recalculate-options] Found ${uniqueProducts.length} unique products to process`);
|
|
69
|
+
// Process in batches
|
|
70
|
+
const results = [];
|
|
71
|
+
const batches = chunkArray(uniqueProducts, BATCH_SIZE);
|
|
72
|
+
for (let batchIdx = 0; batchIdx < batches.length; batchIdx++) {
|
|
73
|
+
const batch = batches[batchIdx];
|
|
74
|
+
logger.info(`[recalculate-options] Processing batch ${batchIdx + 1}/${batches.length} (${batch.length} products)`);
|
|
75
|
+
// Process each product in the batch independently
|
|
76
|
+
const batchResults = await Promise.all(batch.map(product => processProductOptions(req.scope, query, logger, product, masterMaps)));
|
|
77
|
+
results.push(...batchResults);
|
|
78
|
+
}
|
|
79
|
+
// Summary
|
|
80
|
+
const summary = {
|
|
81
|
+
total: results.length,
|
|
82
|
+
success: results.filter(r => r.status === "success").length,
|
|
83
|
+
errors: results.filter(r => r.status === "error").length,
|
|
84
|
+
skipped: results.filter(r => r.status === "skipped").length,
|
|
85
|
+
};
|
|
86
|
+
logger.info(`[recalculate-options] Completed: ${summary.success} success, ${summary.errors} errors, ${summary.skipped} skipped`);
|
|
87
|
+
return (0, api_response_1.sendApiResponse)(res, (0, api_response_1.createSuccessResponse)({
|
|
88
|
+
summary,
|
|
89
|
+
results,
|
|
90
|
+
}, `Processed ${results.length} products: ${summary.success} success, ${summary.errors} errors, ${summary.skipped} skipped`));
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
logger.error("[recalculate-options] Error:", error);
|
|
94
|
+
const errorMessage = error instanceof Error ? error.message : "Internal server error";
|
|
95
|
+
return (0, api_response_1.sendApiResponse)(res, (0, api_response_1.createErrorResponse)(errorMessage, api_response_1.HttpStatus.INTERNAL_SERVER_ERROR, api_response_1.ErrorCode.INTERNAL_ERROR));
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
exports.POST = POST;
|
|
99
|
+
/**
|
|
100
|
+
* Load all master maps once for reuse
|
|
101
|
+
*/
|
|
102
|
+
async function loadMasterMaps(query) {
|
|
103
|
+
const [{ data: rawMasterArr }, { data: qualityMasterArr }, { data: toneMasterArr }, { data: itemSizeMasterArr }, { data: shapeMasterArr },] = await Promise.all([
|
|
104
|
+
query.graph({ entity: "raw_master", fields: ["id", "title", "raw_code"] }),
|
|
105
|
+
query.graph({ entity: "quality_master", fields: ["id", "title", "qly_code"] }),
|
|
106
|
+
query.graph({ entity: "tone_master", fields: ["id", "title", "tone_code"] }),
|
|
107
|
+
query.graph({ entity: "item_size_master", fields: ["id", "title", "item_size_code"] }),
|
|
108
|
+
query.graph({ entity: "shape_master", fields: ["id", "title", "shape_code"] }),
|
|
109
|
+
]);
|
|
110
|
+
const rawMasterMap = new Map();
|
|
111
|
+
rawMasterArr?.forEach((x) => rawMasterMap.set(x.raw_code, x.title));
|
|
112
|
+
const qualityMasterMap = new Map();
|
|
113
|
+
qualityMasterArr?.forEach((x) => qualityMasterMap.set(x.qly_code, x.title));
|
|
114
|
+
const toneMasterMap = new Map();
|
|
115
|
+
toneMasterArr?.forEach((x) => toneMasterMap.set(x.tone_code, x.title));
|
|
116
|
+
const itemSizeMasterMap = new Map();
|
|
117
|
+
itemSizeMasterArr?.forEach((x) => itemSizeMasterMap.set(x.item_size_code, x.title));
|
|
118
|
+
const shapeMasterMap = new Map();
|
|
119
|
+
shapeMasterArr?.forEach((x) => shapeMasterMap.set(x.shape_code, x.title));
|
|
120
|
+
return {
|
|
121
|
+
rawMasterMap,
|
|
122
|
+
qualityMasterMap,
|
|
123
|
+
toneMasterMap,
|
|
124
|
+
itemSizeMasterMap,
|
|
125
|
+
shapeMasterMap,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Process a single product's options
|
|
130
|
+
*/
|
|
131
|
+
async function processProductOptions(scope, query, logger, product, masterMaps) {
|
|
132
|
+
const result = {
|
|
133
|
+
product_id: product.id,
|
|
134
|
+
style_id: product.external_id,
|
|
135
|
+
status: "success",
|
|
136
|
+
updated_variants: 0,
|
|
137
|
+
skipped_variants: [],
|
|
138
|
+
};
|
|
139
|
+
try {
|
|
140
|
+
// Capture old product options
|
|
141
|
+
const oldProductOptions = (product.options || []).map((opt) => ({
|
|
142
|
+
title: opt.title,
|
|
143
|
+
values: opt.values?.map((v) => v.value || v) || [],
|
|
144
|
+
})).filter((opt) => opt.title !== "Default");
|
|
145
|
+
// Get all variants for this product with their current options
|
|
146
|
+
const { data: variants } = await query.graph({
|
|
147
|
+
entity: "product_variant",
|
|
148
|
+
fields: [
|
|
149
|
+
"id",
|
|
150
|
+
"product_id",
|
|
151
|
+
"options.*",
|
|
152
|
+
"extended_variant.id",
|
|
153
|
+
"extended_variant.item_size",
|
|
154
|
+
"extended_variant.stock_type",
|
|
155
|
+
"extended_variant.party_style_details.*",
|
|
156
|
+
],
|
|
157
|
+
filters: {
|
|
158
|
+
product_id: product.id,
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
if (!variants || variants.length === 0) {
|
|
162
|
+
result.status = "skipped";
|
|
163
|
+
result.error = "No variants found";
|
|
164
|
+
// Include old product options even when skipped
|
|
165
|
+
result.product_options = {
|
|
166
|
+
old: oldProductOptions,
|
|
167
|
+
new: oldProductOptions, // No change when skipped
|
|
168
|
+
};
|
|
169
|
+
result.variant_options = [];
|
|
170
|
+
return result;
|
|
171
|
+
}
|
|
172
|
+
// Get extended variant IDs
|
|
173
|
+
const extendedVariantIds = variants
|
|
174
|
+
.map((v) => v.extended_variant?.id)
|
|
175
|
+
.filter(Boolean);
|
|
176
|
+
// Get extended variants with party_style_details
|
|
177
|
+
const { data: extendedVariants } = await query.graph({
|
|
178
|
+
entity: "extended_variant",
|
|
179
|
+
fields: ["id", "item_size", "stock_type", "party_style_details.*"],
|
|
180
|
+
filters: {
|
|
181
|
+
id: extendedVariantIds,
|
|
182
|
+
},
|
|
183
|
+
});
|
|
184
|
+
// Capture old variant options
|
|
185
|
+
const oldVariantOptionsMap = new Map();
|
|
186
|
+
for (const variant of variants) {
|
|
187
|
+
const oldOptions = {};
|
|
188
|
+
if (variant.options) {
|
|
189
|
+
for (const opt of variant.options) {
|
|
190
|
+
if (opt.value) {
|
|
191
|
+
oldOptions[opt.title] = opt.value;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
oldVariantOptionsMap.set(variant.id, oldOptions);
|
|
196
|
+
}
|
|
197
|
+
// Calculate options for each variant
|
|
198
|
+
const productOptionsMap = new Map();
|
|
199
|
+
const variantsToUpdate = [];
|
|
200
|
+
const rawValueMappings = [];
|
|
201
|
+
const newVariantOptionsMap = new Map();
|
|
202
|
+
for (const variant of variants) {
|
|
203
|
+
const extendedVariant = extendedVariants?.find((ev) => ev.id === variant.extended_variant?.id);
|
|
204
|
+
if (!extendedVariant) {
|
|
205
|
+
result.skipped_variants.push({
|
|
206
|
+
id: variant.id,
|
|
207
|
+
reason: "No extended_variant found",
|
|
208
|
+
});
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
const variantOptions = {};
|
|
212
|
+
// Detect solitaire styles based on stock_type
|
|
213
|
+
const stockType = extendedVariant?.stock_type;
|
|
214
|
+
const isSolitaire = stockType === "LG SOLITAIRE" || stockType === "SOLITAIRE";
|
|
215
|
+
// Size
|
|
216
|
+
if (extendedVariant.item_size) {
|
|
217
|
+
const sizeTitle = (masterMaps.itemSizeMasterMap.get(extendedVariant.item_size) ||
|
|
218
|
+
String(extendedVariant.item_size)).trim();
|
|
219
|
+
variantOptions["Size"] = sizeTitle;
|
|
220
|
+
if (!productOptionsMap.has("Size")) {
|
|
221
|
+
productOptionsMap.set("Size", new Set());
|
|
222
|
+
}
|
|
223
|
+
productOptionsMap.get("Size").add(sizeTitle);
|
|
224
|
+
rawValueMappings.push({
|
|
225
|
+
variantId: variant.id,
|
|
226
|
+
optionTitle: "Size",
|
|
227
|
+
optionValue: sizeTitle,
|
|
228
|
+
rawValue: extendedVariant.item_size,
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
// Process party_style_details
|
|
232
|
+
if (extendedVariant.party_style_details) {
|
|
233
|
+
for (const detail of extendedVariant.party_style_details) {
|
|
234
|
+
// Metal options
|
|
235
|
+
if (detail.raw_type === "Metal" && detail.is_base) {
|
|
236
|
+
const qualityTitle = (masterMaps.qualityMasterMap.get(detail.qly_code) || detail.qly_code).trim();
|
|
237
|
+
const rawTitle = (masterMaps.rawMasterMap.get(detail.raw_code) || detail.raw_code).trim();
|
|
238
|
+
const metalValue = `${qualityTitle} ${rawTitle}`.trim();
|
|
239
|
+
variantOptions["Metal"] = metalValue;
|
|
240
|
+
if (!productOptionsMap.has("Metal")) {
|
|
241
|
+
productOptionsMap.set("Metal", new Set());
|
|
242
|
+
}
|
|
243
|
+
productOptionsMap.get("Metal").add(metalValue);
|
|
244
|
+
rawValueMappings.push({
|
|
245
|
+
variantId: variant.id,
|
|
246
|
+
optionTitle: "Metal",
|
|
247
|
+
optionValue: metalValue,
|
|
248
|
+
rawValue: `${detail.qly_code || ""}:${detail.raw_code || ""}`.trim(),
|
|
249
|
+
});
|
|
250
|
+
// Metal Color
|
|
251
|
+
if (detail.tone_code) {
|
|
252
|
+
let colorTitle = masterMaps.toneMasterMap.get(detail.tone_code) || detail.tone_code;
|
|
253
|
+
// Fallback to static mappings
|
|
254
|
+
if (!masterMaps.toneMasterMap.has(detail.tone_code)) {
|
|
255
|
+
if (detail.tone_code === "R")
|
|
256
|
+
colorTitle = "Rose";
|
|
257
|
+
else if (detail.tone_code === "Y")
|
|
258
|
+
colorTitle = "Yellow";
|
|
259
|
+
else if (detail.tone_code === "W")
|
|
260
|
+
colorTitle = "White";
|
|
261
|
+
else if (detail.tone_code === "YRW")
|
|
262
|
+
colorTitle = "YELLOW/ROSE/WHITE";
|
|
263
|
+
else if (detail.tone_code === "YW")
|
|
264
|
+
colorTitle = "YELLOW/WHITE";
|
|
265
|
+
else if (detail.tone_code === "RW")
|
|
266
|
+
colorTitle = "ROSE/WHITE";
|
|
267
|
+
else if (detail.tone_code === "BU")
|
|
268
|
+
colorTitle = "BLUE";
|
|
269
|
+
else if (detail.tone_code === "BL")
|
|
270
|
+
colorTitle = "BLACK";
|
|
271
|
+
}
|
|
272
|
+
colorTitle = colorTitle.trim();
|
|
273
|
+
variantOptions["Metal Color"] = colorTitle;
|
|
274
|
+
if (!productOptionsMap.has("Metal Color")) {
|
|
275
|
+
productOptionsMap.set("Metal Color", new Set());
|
|
276
|
+
}
|
|
277
|
+
productOptionsMap.get("Metal Color").add(colorTitle);
|
|
278
|
+
rawValueMappings.push({
|
|
279
|
+
variantId: variant.id,
|
|
280
|
+
optionTitle: "Metal Color",
|
|
281
|
+
optionValue: colorTitle,
|
|
282
|
+
rawValue: detail.tone_code || "",
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
// Diamond Quality
|
|
287
|
+
if (detail.raw_type === "Diamond" &&
|
|
288
|
+
detail.tone_code &&
|
|
289
|
+
detail.qly_code &&
|
|
290
|
+
detail.is_base) {
|
|
291
|
+
const toneTitle = (masterMaps.toneMasterMap.get(detail.tone_code) || detail.tone_code).trim();
|
|
292
|
+
const qualityTitle = (masterMaps.qualityMasterMap.get(detail.qly_code) || detail.qly_code).trim();
|
|
293
|
+
const diamondValue = `${toneTitle} ${qualityTitle}`.trim();
|
|
294
|
+
variantOptions["Diamond Quality"] = diamondValue;
|
|
295
|
+
if (!productOptionsMap.has("Diamond Quality")) {
|
|
296
|
+
productOptionsMap.set("Diamond Quality", new Set());
|
|
297
|
+
}
|
|
298
|
+
productOptionsMap.get("Diamond Quality").add(diamondValue);
|
|
299
|
+
rawValueMappings.push({
|
|
300
|
+
variantId: variant.id,
|
|
301
|
+
optionTitle: "Diamond Quality",
|
|
302
|
+
optionValue: diamondValue,
|
|
303
|
+
rawValue: `${detail.tone_code || ""}:${detail.qly_code || ""}`.trim(),
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
// Shape and Carat for solitaire
|
|
307
|
+
if (isSolitaire &&
|
|
308
|
+
detail.raw_type === "Diamond" &&
|
|
309
|
+
detail.raw_code === "LGS" &&
|
|
310
|
+
detail.is_base) {
|
|
311
|
+
const shapeTitle = (masterMaps.shapeMasterMap.get(detail.shape_code) ||
|
|
312
|
+
String(detail.shape_code || "")).trim();
|
|
313
|
+
if (shapeTitle) {
|
|
314
|
+
variantOptions["Shape"] = shapeTitle;
|
|
315
|
+
if (!productOptionsMap.has("Shape")) {
|
|
316
|
+
productOptionsMap.set("Shape", new Set());
|
|
317
|
+
}
|
|
318
|
+
productOptionsMap.get("Shape").add(shapeTitle);
|
|
319
|
+
rawValueMappings.push({
|
|
320
|
+
variantId: variant.id,
|
|
321
|
+
optionTitle: "Shape",
|
|
322
|
+
optionValue: shapeTitle,
|
|
323
|
+
rawValue: detail.shape_code || "",
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
const weightStr = String(detail?.weight || "").trim();
|
|
327
|
+
if (weightStr) {
|
|
328
|
+
variantOptions["Carat"] = weightStr;
|
|
329
|
+
if (!productOptionsMap.has("Carat")) {
|
|
330
|
+
productOptionsMap.set("Carat", new Set());
|
|
331
|
+
}
|
|
332
|
+
productOptionsMap.get("Carat").add(weightStr);
|
|
333
|
+
rawValueMappings.push({
|
|
334
|
+
variantId: variant.id,
|
|
335
|
+
optionTitle: "Carat",
|
|
336
|
+
optionValue: weightStr,
|
|
337
|
+
rawValue: weightStr,
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
// Check if we have all required options
|
|
344
|
+
const productOptionTitles = product.options?.map((opt) => opt.title) || [];
|
|
345
|
+
const hasAllOptions = productOptionTitles.every((title) => variantOptions[title] !== undefined);
|
|
346
|
+
if (!hasAllOptions) {
|
|
347
|
+
const missingOptions = productOptionTitles.filter((title) => variantOptions[title] === undefined);
|
|
348
|
+
result.skipped_variants.push({
|
|
349
|
+
id: variant.id,
|
|
350
|
+
reason: `Missing options: [${missingOptions.join(", ")}]`,
|
|
351
|
+
});
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
// Sort options alphabetically
|
|
355
|
+
const sortedOptions = {};
|
|
356
|
+
Object.keys(variantOptions)
|
|
357
|
+
.sort((a, b) => a.localeCompare(b))
|
|
358
|
+
.forEach((key) => {
|
|
359
|
+
sortedOptions[key] = variantOptions[key];
|
|
360
|
+
});
|
|
361
|
+
variantsToUpdate.push({
|
|
362
|
+
id: variant.id,
|
|
363
|
+
options: sortedOptions,
|
|
364
|
+
});
|
|
365
|
+
// Store new variant options
|
|
366
|
+
newVariantOptionsMap.set(variant.id, sortedOptions);
|
|
367
|
+
}
|
|
368
|
+
// STEP 1: Update product options to include all values
|
|
369
|
+
const productOptions = Array.from(productOptionsMap.entries())
|
|
370
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
371
|
+
.map(([title, values]) => ({
|
|
372
|
+
title,
|
|
373
|
+
values: Array.from(values).sort((a, b) => a.localeCompare(b)),
|
|
374
|
+
}));
|
|
375
|
+
if (productOptions.length > 0) {
|
|
376
|
+
await (0, core_flows_1.updateProductsWorkflow)(scope).run({
|
|
377
|
+
input: {
|
|
378
|
+
products: [{ id: product.id, options: productOptions }],
|
|
379
|
+
},
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
// STEP 2: Update variant options
|
|
383
|
+
if (variantsToUpdate.length > 0) {
|
|
384
|
+
await (0, core_flows_1.updateProductVariantsWorkflow)(scope).run({
|
|
385
|
+
input: {
|
|
386
|
+
product_variants: variantsToUpdate,
|
|
387
|
+
},
|
|
388
|
+
});
|
|
389
|
+
// Update variant option metadata with raw values
|
|
390
|
+
if (rawValueMappings.length > 0) {
|
|
391
|
+
await (0, update_variant_option_metadata_1.updateVariantOptionMetadata)(scope, rawValueMappings);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
// Fetch new product options after update
|
|
395
|
+
const { data: updatedProduct } = await query.graph({
|
|
396
|
+
entity: "product",
|
|
397
|
+
fields: ["id", "options.*"],
|
|
398
|
+
filters: {
|
|
399
|
+
id: product.id,
|
|
400
|
+
},
|
|
401
|
+
});
|
|
402
|
+
const newProductOptions = (updatedProduct?.[0]?.options || []).map((opt) => ({
|
|
403
|
+
title: opt.title,
|
|
404
|
+
values: opt.values?.map((v) => v.value || v) || [],
|
|
405
|
+
})).filter((opt) => opt.title !== "Default");
|
|
406
|
+
// Build variant options comparison
|
|
407
|
+
const variantOptionsComparison = [];
|
|
408
|
+
for (const variant of variants) {
|
|
409
|
+
const oldOptions = oldVariantOptionsMap.get(variant.id) || {};
|
|
410
|
+
const newOptions = newVariantOptionsMap.get(variant.id) || {};
|
|
411
|
+
// Only include variants that were updated
|
|
412
|
+
if (variantsToUpdate.some(v => v.id === variant.id)) {
|
|
413
|
+
variantOptionsComparison.push({
|
|
414
|
+
variant_id: variant.id,
|
|
415
|
+
old: oldOptions,
|
|
416
|
+
new: newOptions,
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
// Include old and new options in result
|
|
421
|
+
result.product_options = {
|
|
422
|
+
old: oldProductOptions,
|
|
423
|
+
new: newProductOptions,
|
|
424
|
+
};
|
|
425
|
+
result.variant_options = variantOptionsComparison;
|
|
426
|
+
result.updated_variants = variantsToUpdate.length;
|
|
427
|
+
logger.info(`[recalculate-options] Product ${product.external_id || product.id}: ${variantsToUpdate.length} updated, ${result.skipped_variants.length} skipped`);
|
|
428
|
+
}
|
|
429
|
+
catch (error) {
|
|
430
|
+
result.status = "error";
|
|
431
|
+
result.error = error instanceof Error ? error.message : "Unknown error";
|
|
432
|
+
logger.error(`[recalculate-options] Error processing product ${product.external_id || product.id}:`, error);
|
|
433
|
+
}
|
|
434
|
+
return result;
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Split array into chunks
|
|
438
|
+
*/
|
|
439
|
+
function chunkArray(array, size) {
|
|
440
|
+
const chunks = [];
|
|
441
|
+
for (let i = 0; i < array.length; i += size) {
|
|
442
|
+
chunks.push(array.slice(i, i + size));
|
|
443
|
+
}
|
|
444
|
+
return chunks;
|
|
445
|
+
}
|
|
446
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL3ZhcmlhbnQtb3B0aW9ucy9yZWNhbGN1bGF0ZS9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFDQSxxREFBc0U7QUFDdEUsNERBR3FDO0FBRXJDLCtEQU1zQztBQUN0QyxpSEFHc0U7QUFFdEUsTUFBTSxVQUFVLEdBQUcsRUFBRSxDQUFDLENBQUMsZ0NBQWdDO0FBNEJ2RDs7Ozs7Ozs7Ozs7Ozs7R0FjRztBQUNJLE1BQU0sSUFBSSxHQUFHLEtBQUssRUFDdkIsR0FBK0IsRUFDL0IsR0FBbUIsRUFDbkIsRUFBRTtJQUNGLE1BQU0sS0FBSyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLGlDQUF5QixDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ2pFLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLGlDQUF5QixDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRW5FLE1BQU0sRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQUUsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLElBQUksRUFBRSxDQUt2RSxDQUFDO0lBRUYsNkJBQTZCO0lBQzdCLE1BQU0sV0FBVyxHQUFHLFNBQVMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDOUQsTUFBTSxhQUFhLEdBQUcsV0FBVyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUV0RSxJQUFJLFdBQVcsQ0FBQyxNQUFNLEtBQUssQ0FBQyxJQUFJLGFBQWEsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDM0QsT0FBTyxJQUFB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
|