multicloud_rule_manager 1.1.60 → 1.1.61
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 +219 -0
- package/package.json +1 -1
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import XLSX from "xlsx";
|
|
3
|
+
import { getAlias } from "../utils/aliasManager.js";
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
command: "retrieveproduct <alias> <productName>",
|
|
7
|
+
describe: "Recupera struttura prodotto e genera Excel",
|
|
8
|
+
handler: async (argv) => {
|
|
9
|
+
try {
|
|
10
|
+
console.log("🔹 Retrieve in corso..");
|
|
11
|
+
|
|
12
|
+
const cred = getAlias(argv.alias);
|
|
13
|
+
|
|
14
|
+
// =========================
|
|
15
|
+
// 🔐 TOKEN
|
|
16
|
+
// =========================
|
|
17
|
+
const loginResp = await fetch(
|
|
18
|
+
`https://login-eon-no-prod.bit2win.cloud/auth/realms/${cred.realm}/protocol/openid-connect/token`,
|
|
19
|
+
{
|
|
20
|
+
method: "POST",
|
|
21
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
22
|
+
body: new URLSearchParams({
|
|
23
|
+
client_id: cred.clientId,
|
|
24
|
+
client_secret: cred.clientSecret,
|
|
25
|
+
username: cred.username,
|
|
26
|
+
password: cred.password,
|
|
27
|
+
grant_type: "password"
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
const { access_token } = await loginResp.json();
|
|
33
|
+
|
|
34
|
+
if (!access_token) {
|
|
35
|
+
throw new Error("Token non ricevuto");
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const headers = {
|
|
39
|
+
Authorization: `Bearer ${access_token}`,
|
|
40
|
+
Accept: "application/json"
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// =========================
|
|
44
|
+
// 📦 PRODUCTS
|
|
45
|
+
// =========================
|
|
46
|
+
const productsResp = await fetch(
|
|
47
|
+
`https://${cred.realm}.bit2win.cloud/api/data/v1/products/`,
|
|
48
|
+
{ headers }
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
const products = await productsResp.json();
|
|
52
|
+
|
|
53
|
+
const product = products.find(p => p.name === argv.productName);
|
|
54
|
+
|
|
55
|
+
if (!product) {
|
|
56
|
+
throw new Error(`Prodotto "${argv.productName}" non trovato`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const rootGuid = product.guid;
|
|
60
|
+
|
|
61
|
+
// =========================
|
|
62
|
+
// 🌳 STRUCTURE
|
|
63
|
+
// =========================
|
|
64
|
+
const structResp = await fetch(
|
|
65
|
+
`https://${cred.realm}.bit2win.cloud/api/data/v1/products_structure/`,
|
|
66
|
+
{ headers }
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
const structure = await structResp.json();
|
|
70
|
+
|
|
71
|
+
// =========================
|
|
72
|
+
// 📂 HELPERS
|
|
73
|
+
// =========================
|
|
74
|
+
const sortByName = arr =>
|
|
75
|
+
arr.sort((a, b) => (a.name || "").localeCompare(b.name || ""));
|
|
76
|
+
|
|
77
|
+
const getCategories = () =>
|
|
78
|
+
sortByName(
|
|
79
|
+
structure.filter(
|
|
80
|
+
e => e.parent_guid === rootGuid && e.type === "category"
|
|
81
|
+
)
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
const getChildren = (categoryGuid) =>
|
|
85
|
+
sortByName(
|
|
86
|
+
structure.filter(e => e.parent_guid === categoryGuid)
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
// =========================
|
|
90
|
+
// 📡 FAMILIES
|
|
91
|
+
// =========================
|
|
92
|
+
const getFamilies = async (productId) => {
|
|
93
|
+
const resp = await fetch(
|
|
94
|
+
`https://${cred.realm}.bit2win.cloud/api/catalog/v1/products/${productId}/families`,
|
|
95
|
+
{ headers }
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
const data = await resp.json();
|
|
99
|
+
|
|
100
|
+
return sortByName(
|
|
101
|
+
(data || []).map(f => ({
|
|
102
|
+
name: f.name,
|
|
103
|
+
visible: f.visible,
|
|
104
|
+
visible_web: f.visible_web,
|
|
105
|
+
attributes: sortByName(
|
|
106
|
+
(f.attributes || []).map(a => ({
|
|
107
|
+
name: a.name,
|
|
108
|
+
value_default: a.value_default,
|
|
109
|
+
read_only: a.read_only,
|
|
110
|
+
required: a.required,
|
|
111
|
+
visible: a.visible,
|
|
112
|
+
domains: sortByName(
|
|
113
|
+
(a.domains || []).map(d => ({
|
|
114
|
+
value: d.value,
|
|
115
|
+
visible: d.visible,
|
|
116
|
+
default: d.default
|
|
117
|
+
}))
|
|
118
|
+
)
|
|
119
|
+
}))
|
|
120
|
+
)
|
|
121
|
+
}))
|
|
122
|
+
);
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
// =========================
|
|
126
|
+
// 📊 DATASET 1
|
|
127
|
+
// =========================
|
|
128
|
+
const rows1 = [];
|
|
129
|
+
|
|
130
|
+
const categories = getCategories();
|
|
131
|
+
|
|
132
|
+
for (const cat of categories) {
|
|
133
|
+
const children = getChildren(cat.guid);
|
|
134
|
+
|
|
135
|
+
if (children.length === 0) {
|
|
136
|
+
rows1.push({
|
|
137
|
+
product: product.name,
|
|
138
|
+
category: cat.name,
|
|
139
|
+
child: ""
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
for (const child of children) {
|
|
144
|
+
rows1.push({
|
|
145
|
+
product: product.name,
|
|
146
|
+
category: cat.name,
|
|
147
|
+
child: child.name
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// =========================
|
|
153
|
+
// 📊 DATASET 2
|
|
154
|
+
// =========================
|
|
155
|
+
const rows2 = [];
|
|
156
|
+
|
|
157
|
+
for (const cat of categories) {
|
|
158
|
+
const children = getChildren(cat.guid);
|
|
159
|
+
|
|
160
|
+
for (const child of children) {
|
|
161
|
+
if (!child.product_id) continue;
|
|
162
|
+
|
|
163
|
+
const families = await getFamilies(child.product_id);
|
|
164
|
+
|
|
165
|
+
for (const f of families) {
|
|
166
|
+
for (const attr of f.attributes) {
|
|
167
|
+
for (const dom of attr.domains) {
|
|
168
|
+
rows2.push({
|
|
169
|
+
product: product.name,
|
|
170
|
+
category: cat.name,
|
|
171
|
+
child: child.name,
|
|
172
|
+
family: f.name,
|
|
173
|
+
family_visible: f.visible,
|
|
174
|
+
family_visible_web: f.visible_web,
|
|
175
|
+
attribute: attr.name,
|
|
176
|
+
attr_default: attr.value_default,
|
|
177
|
+
attr_required: attr.required,
|
|
178
|
+
attr_visible: attr.visible,
|
|
179
|
+
domain_value: dom.value,
|
|
180
|
+
domain_visible: dom.visible,
|
|
181
|
+
domain_default: dom.default
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// =========================
|
|
190
|
+
// 🔤 SORT GLOBALE
|
|
191
|
+
// =========================
|
|
192
|
+
const sortRows = (rows) =>
|
|
193
|
+
rows.sort((a, b) =>
|
|
194
|
+
Object.values(a).join("|").localeCompare(Object.values(b).join("|"))
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
const sorted1 = sortRows(rows1);
|
|
198
|
+
const sorted2 = sortRows(rows2);
|
|
199
|
+
|
|
200
|
+
// =========================
|
|
201
|
+
// 📁 EXCEL
|
|
202
|
+
// =========================
|
|
203
|
+
const writeExcel = (fileName, data) => {
|
|
204
|
+
const ws = XLSX.utils.json_to_sheet(data);
|
|
205
|
+
const wb = XLSX.utils.book_new();
|
|
206
|
+
XLSX.utils.book_append_sheet(wb, ws, "Sheet1");
|
|
207
|
+
XLSX.writeFile(wb, fileName);
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
writeExcel("product_structure.xlsx", sorted1);
|
|
211
|
+
writeExcel("product_details.xlsx", sorted2);
|
|
212
|
+
|
|
213
|
+
console.log("✅ Excel generati con successo");
|
|
214
|
+
|
|
215
|
+
} catch (err) {
|
|
216
|
+
console.error("❌ Errore:", err.message);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
};
|