multicloud_rule_manager 1.1.79 โ 1.1.81
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/commands/retrieveproduct.js +131 -127
- package/package.json +1 -1
|
@@ -5,175 +5,201 @@ import { getAlias } from "../utils/aliasManager.js";
|
|
|
5
5
|
export default {
|
|
6
6
|
command: "retrieveproduct <alias> <productName>",
|
|
7
7
|
describe: "Recupera struttura prodotto e genera Excel",
|
|
8
|
-
|
|
8
|
+
|
|
9
|
+
handler: async (argv) => {
|
|
9
10
|
try {
|
|
10
11
|
console.log("๐น Retrieve in corso..");
|
|
11
12
|
console.log("๐น Recupero credenziali per alias:", argv.alias);
|
|
13
|
+
|
|
12
14
|
const cred = getAlias(argv.alias);
|
|
13
15
|
|
|
14
|
-
//
|
|
16
|
+
// =========================
|
|
17
|
+
// ๐ข CONTATORI GLOBALI
|
|
18
|
+
// =========================
|
|
19
|
+
let totalCategories = 0;
|
|
20
|
+
let totalChildren = 0;
|
|
21
|
+
let totalFamilies = 0;
|
|
22
|
+
let totalAttributes = 0;
|
|
23
|
+
let totalDomains = 0;
|
|
24
|
+
|
|
25
|
+
// =========================
|
|
26
|
+
// ๐ TOKEN
|
|
27
|
+
// =========================
|
|
15
28
|
console.log("๐น Inizio richiesta token...");
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
|
|
30
|
+
const loginResp = await fetch(
|
|
31
|
+
`https://login-eon-no-prod.bit2win.cloud/auth/realms/${cred.realm}/protocol/openid-connect/token`,
|
|
32
|
+
{
|
|
33
|
+
method: "POST",
|
|
34
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
35
|
+
body: new URLSearchParams({
|
|
36
|
+
client_id: cred.clientId,
|
|
37
|
+
client_secret: cred.clientSecret,
|
|
38
|
+
username: cred.username,
|
|
39
|
+
password: cred.password,
|
|
40
|
+
grant_type: "password",
|
|
41
|
+
}),
|
|
42
|
+
}
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
const loginData = await loginResp.json();
|
|
29
46
|
const access_token = loginData.access_token;
|
|
30
47
|
|
|
31
48
|
if (!access_token) {
|
|
32
|
-
throw new Error("Token non ricevuto
|
|
49
|
+
throw new Error("Token non ricevuto");
|
|
33
50
|
}
|
|
34
51
|
|
|
52
|
+
console.log("โ
Token ricevuto");
|
|
35
53
|
|
|
54
|
+
// =========================
|
|
55
|
+
// ๐ฆ PRODUCTS
|
|
56
|
+
// =========================
|
|
57
|
+
console.log("๐น Chiamo products...");
|
|
36
58
|
|
|
37
|
-
|
|
38
|
-
// --- SECONDA CHIAMATA: retrieve ---
|
|
39
|
-
console.log("๐น Inizio richiesta dati API...");
|
|
40
59
|
const apiResp = await fetch(
|
|
41
|
-
`https://${cred.realm}.bit2win.cloud/api/data/v1/
|
|
42
|
-
|
|
43
|
-
method: "GET",
|
|
60
|
+
`https://${cred.realm}.bit2win.cloud/api/data/v1/products`,
|
|
61
|
+
{
|
|
44
62
|
headers: {
|
|
45
|
-
|
|
46
|
-
|
|
63
|
+
Authorization: `Bearer ${access_token}`,
|
|
64
|
+
Accept: "application/json",
|
|
47
65
|
},
|
|
48
|
-
redirect: "manual"
|
|
49
66
|
}
|
|
50
67
|
);
|
|
51
68
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const data = await apiResp.json();
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
// Controlla che sia array
|
|
58
|
-
if (!Array.isArray(data)) {
|
|
59
|
-
throw new Error("La risposta API non รจ una lista di oggetti");
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
console.log(" Chiamo products"+argv.productName);
|
|
63
69
|
const products = await safeJson(apiResp, "products");
|
|
70
|
+
console.log(`๐ฆ Totale products ricevuti: ${products.length}`);
|
|
64
71
|
|
|
65
|
-
|
|
66
|
-
|
|
72
|
+
const product = products.find(
|
|
73
|
+
(p) => p.name === argv.productName
|
|
74
|
+
);
|
|
67
75
|
|
|
68
76
|
if (!product) {
|
|
69
77
|
throw new Error(`Prodotto "${argv.productName}" non trovato`);
|
|
70
78
|
}
|
|
71
79
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
80
|
+
console.log(`โ
Prodotto trovato: ${product.name}`);
|
|
75
81
|
|
|
82
|
+
const rootGuid = product.guid;
|
|
76
83
|
|
|
77
84
|
// =========================
|
|
78
85
|
// ๐ณ STRUCTURE
|
|
79
86
|
// =========================
|
|
80
|
-
|
|
81
|
-
console.log("Chiamo products structure");
|
|
87
|
+
console.log("๐น Chiamo structure...");
|
|
82
88
|
|
|
83
89
|
const structResp = await fetch(
|
|
84
|
-
`https://${cred.realm}.bit2win.cloud/api/data/v1/products_structure
|
|
85
|
-
|
|
86
|
-
method: "GET",
|
|
90
|
+
`https://${cred.realm}.bit2win.cloud/api/data/v1/products_structure`,
|
|
91
|
+
{
|
|
87
92
|
headers: {
|
|
88
|
-
|
|
89
|
-
|
|
93
|
+
Authorization: `Bearer ${access_token}`,
|
|
94
|
+
Accept: "application/json",
|
|
90
95
|
},
|
|
91
|
-
redirect: "manual"
|
|
92
96
|
}
|
|
93
97
|
);
|
|
94
98
|
|
|
95
|
-
const structure = await safeJson(
|
|
99
|
+
const structure = await safeJson(
|
|
100
|
+
structResp,
|
|
101
|
+
"products_structure"
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
console.log(`๐ณ Totale elementi structure: ${structure.length}`);
|
|
96
105
|
|
|
97
106
|
// =========================
|
|
98
107
|
// ๐ HELPERS
|
|
99
108
|
// =========================
|
|
100
|
-
const sortByName = arr =>
|
|
101
|
-
arr.sort((a, b) =>
|
|
109
|
+
const sortByName = (arr) =>
|
|
110
|
+
arr.sort((a, b) =>
|
|
111
|
+
(a.name || "").localeCompare(b.name || "")
|
|
112
|
+
);
|
|
102
113
|
|
|
103
114
|
const getCategories = () =>
|
|
104
115
|
sortByName(
|
|
105
116
|
structure.filter(
|
|
106
|
-
e =>
|
|
117
|
+
(e) =>
|
|
118
|
+
e.parent_guid === rootGuid &&
|
|
119
|
+
e.type === "category"
|
|
107
120
|
)
|
|
108
121
|
);
|
|
109
122
|
|
|
110
123
|
const getChildren = (categoryGuid) =>
|
|
111
124
|
sortByName(
|
|
112
|
-
structure.filter(
|
|
125
|
+
structure.filter(
|
|
126
|
+
(e) => e.parent_guid === categoryGuid
|
|
127
|
+
)
|
|
113
128
|
);
|
|
114
129
|
|
|
115
130
|
// =========================
|
|
116
131
|
// ๐ก FAMILIES
|
|
117
132
|
// =========================
|
|
118
|
-
|
|
119
|
-
console.log("Chiamo families");
|
|
120
|
-
|
|
121
133
|
const getFamilies = async (productId) => {
|
|
122
134
|
const resp = await fetch(
|
|
123
135
|
`https://${cred.realm}.bit2win.cloud/api/catalog/v1/products/${productId}/families`,
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
136
|
+
{
|
|
137
|
+
headers: {
|
|
138
|
+
Authorization: `Bearer ${access_token}`,
|
|
139
|
+
Accept: "application/json",
|
|
140
|
+
},
|
|
141
|
+
}
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
const data = await safeJson(
|
|
145
|
+
resp,
|
|
146
|
+
`families:${productId}`
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
console.log(
|
|
150
|
+
`๐จโ๐ฉโ๐ง Product ${productId} โ ${data.length} families`
|
|
151
|
+
);
|
|
134
152
|
|
|
135
|
-
|
|
153
|
+
totalFamilies += data.length;
|
|
136
154
|
|
|
137
|
-
return (data || [])
|
|
138
|
-
|
|
139
|
-
|
|
155
|
+
return (data || []).map((f) => {
|
|
156
|
+
totalAttributes += (f.attributes || []).length;
|
|
157
|
+
|
|
158
|
+
return {
|
|
140
159
|
name: f.name,
|
|
141
160
|
visible: f.visible,
|
|
142
161
|
visible_web: f.visible_web,
|
|
143
|
-
attributes: (f.attributes || [])
|
|
144
|
-
|
|
145
|
-
|
|
162
|
+
attributes: (f.attributes || []).map((a) => {
|
|
163
|
+
totalDomains += (a.domains || []).length;
|
|
164
|
+
|
|
165
|
+
return {
|
|
146
166
|
name: a.name,
|
|
147
167
|
value_default: a.value_default,
|
|
148
168
|
read_only: a.read_only,
|
|
149
169
|
required: a.required,
|
|
150
170
|
visible: a.visible,
|
|
151
|
-
domains:
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
default: d.default
|
|
157
|
-
}))
|
|
158
|
-
}))
|
|
159
|
-
}));
|
|
171
|
+
domains: a.domains || [],
|
|
172
|
+
};
|
|
173
|
+
}),
|
|
174
|
+
};
|
|
175
|
+
});
|
|
160
176
|
};
|
|
161
177
|
|
|
162
178
|
// =========================
|
|
163
|
-
// ๐ DATASET
|
|
179
|
+
// ๐ DATASET
|
|
164
180
|
// =========================
|
|
165
181
|
const rows1 = [];
|
|
182
|
+
const rows2 = [];
|
|
166
183
|
|
|
167
184
|
const categories = getCategories();
|
|
185
|
+
totalCategories = categories.length;
|
|
186
|
+
|
|
187
|
+
console.log(`๐ Totale categorie: ${categories.length}`);
|
|
168
188
|
|
|
169
189
|
for (const cat of categories) {
|
|
170
190
|
const children = getChildren(cat.guid);
|
|
171
191
|
|
|
192
|
+
console.log(
|
|
193
|
+
`โก๏ธ Categoria "${cat.name}" โ ${children.length} children`
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
totalChildren += children.length;
|
|
197
|
+
|
|
172
198
|
if (children.length === 0) {
|
|
173
199
|
rows1.push({
|
|
174
200
|
product: product.name,
|
|
175
201
|
category: cat.name,
|
|
176
|
-
child: ""
|
|
202
|
+
child: "",
|
|
177
203
|
});
|
|
178
204
|
}
|
|
179
205
|
|
|
@@ -181,23 +207,14 @@ export default {
|
|
|
181
207
|
rows1.push({
|
|
182
208
|
product: product.name,
|
|
183
209
|
category: cat.name,
|
|
184
|
-
child: child.name
|
|
210
|
+
child: child.name,
|
|
185
211
|
});
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// =========================
|
|
190
|
-
// ๐ DATASET 2
|
|
191
|
-
// =========================
|
|
192
|
-
const rows2 = [];
|
|
193
|
-
|
|
194
|
-
for (const cat of categories) {
|
|
195
|
-
const children = getChildren(cat.guid);
|
|
196
212
|
|
|
197
|
-
for (const child of children) {
|
|
198
213
|
if (!child.product_id) continue;
|
|
199
214
|
|
|
200
|
-
const families = await getFamilies(
|
|
215
|
+
const families = await getFamilies(
|
|
216
|
+
child.product_id
|
|
217
|
+
);
|
|
201
218
|
|
|
202
219
|
for (const f of families) {
|
|
203
220
|
for (const attr of f.attributes) {
|
|
@@ -207,15 +224,8 @@ export default {
|
|
|
207
224
|
category: cat.name,
|
|
208
225
|
child: child.name,
|
|
209
226
|
family: f.name,
|
|
210
|
-
family_visible: f.visible,
|
|
211
|
-
family_visible_web: f.visible_web,
|
|
212
227
|
attribute: attr.name,
|
|
213
|
-
attr_default: attr.value_default,
|
|
214
|
-
attr_required: attr.required,
|
|
215
|
-
attr_visible: attr.visible,
|
|
216
228
|
domain_value: dom.value,
|
|
217
|
-
domain_visible: dom.visible,
|
|
218
|
-
domain_default: dom.default
|
|
219
229
|
});
|
|
220
230
|
}
|
|
221
231
|
}
|
|
@@ -224,15 +234,17 @@ export default {
|
|
|
224
234
|
}
|
|
225
235
|
|
|
226
236
|
// =========================
|
|
227
|
-
//
|
|
237
|
+
// ๐ RISULTATI
|
|
228
238
|
// =========================
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
Object.values(a).join("|").localeCompare(Object.values(b).join("|"))
|
|
232
|
-
);
|
|
239
|
+
console.log(`๐ Righe dataset 1: ${rows1.length}`);
|
|
240
|
+
console.log(`๐ Righe dataset 2: ${rows2.length}`);
|
|
233
241
|
|
|
234
|
-
|
|
235
|
-
|
|
242
|
+
console.log("๐ STATISTICHE GLOBALI:");
|
|
243
|
+
console.log(`Categorie: ${totalCategories}`);
|
|
244
|
+
console.log(`Children: ${totalChildren}`);
|
|
245
|
+
console.log(`Families: ${totalFamilies}`);
|
|
246
|
+
console.log(`Attributi: ${totalAttributes}`);
|
|
247
|
+
console.log(`Domini: ${totalDomains}`);
|
|
236
248
|
|
|
237
249
|
// =========================
|
|
238
250
|
// ๐ EXCEL
|
|
@@ -244,8 +256,8 @@ export default {
|
|
|
244
256
|
XLSX.writeFile(wb, fileName);
|
|
245
257
|
};
|
|
246
258
|
|
|
247
|
-
writeExcel("product_structure.xlsx",
|
|
248
|
-
writeExcel("product_details.xlsx",
|
|
259
|
+
writeExcel("product_structure.xlsx", rows1);
|
|
260
|
+
writeExcel("product_details.xlsx", rows2);
|
|
249
261
|
|
|
250
262
|
console.log("โ
Excel generati con successo");
|
|
251
263
|
|
|
@@ -253,28 +265,20 @@ export default {
|
|
|
253
265
|
console.error("โ Errore:", err.message);
|
|
254
266
|
}
|
|
255
267
|
|
|
256
|
-
|
|
257
|
-
|
|
258
268
|
async function safeJson(resp, label) {
|
|
259
269
|
const text = await resp.text();
|
|
260
|
-
console.log("RAW products:", resp);
|
|
261
|
-
console.log("RAW products:", text);
|
|
262
270
|
|
|
263
271
|
if (!resp.ok) {
|
|
264
|
-
throw new Error(
|
|
272
|
+
throw new Error(
|
|
273
|
+
`${label} HTTP ${resp.status}: ${text.slice(0, 200)}`
|
|
274
|
+
);
|
|
265
275
|
}
|
|
266
276
|
|
|
267
277
|
if (!text) {
|
|
268
278
|
throw new Error(`${label} risposta vuota`);
|
|
269
279
|
}
|
|
270
280
|
|
|
271
|
-
|
|
272
|
-
return JSON.parse(text);
|
|
273
|
-
} catch (e) {
|
|
274
|
-
throw new Error(`${label} NON JSON valido: ${text.slice(0, 200)}`);
|
|
275
|
-
}
|
|
281
|
+
return JSON.parse(text);
|
|
276
282
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
}
|
|
283
|
+
},
|
|
280
284
|
};
|