@simonfestl/husky-cli 1.12.0 → 1.13.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.
- package/dist/commands/biz/emove.d.ts +12 -0
- package/dist/commands/biz/emove.js +249 -0
- package/dist/commands/biz/skuterzone.d.ts +12 -0
- package/dist/commands/biz/skuterzone.js +248 -0
- package/dist/commands/biz/wattiz.d.ts +12 -0
- package/dist/commands/biz/wattiz.js +252 -0
- package/dist/commands/biz.js +7 -1
- package/dist/commands/config.d.ts +7 -0
- package/dist/commands/config.js +12 -1
- package/dist/lib/biz/emove-playwright.d.ts +22 -0
- package/dist/lib/biz/emove-playwright.js +289 -0
- package/dist/lib/biz/emove-types.d.ts +60 -0
- package/dist/lib/biz/emove-types.js +7 -0
- package/dist/lib/biz/skuterzone-playwright.d.ts +21 -0
- package/dist/lib/biz/skuterzone-playwright.js +271 -0
- package/dist/lib/biz/skuterzone-types.d.ts +60 -0
- package/dist/lib/biz/skuterzone-types.js +7 -0
- package/dist/lib/biz/wattiz-playwright.d.ts +22 -0
- package/dist/lib/biz/wattiz-playwright.js +380 -0
- package/dist/lib/biz/wattiz-types.d.ts +61 -0
- package/dist/lib/biz/wattiz-types.js +6 -0
- package/package.json +1 -1
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Husky Biz Emove Command
|
|
3
|
+
*
|
|
4
|
+
* Manages emovedistribution.com (B2B e-mobility parts supplier) via web scraping
|
|
5
|
+
* WooCommerce platform integration (Spanish locale)
|
|
6
|
+
* - Parts search and catalog browsing
|
|
7
|
+
* - Order history and details
|
|
8
|
+
* - Invoice download
|
|
9
|
+
*/
|
|
10
|
+
import { Command } from "commander";
|
|
11
|
+
export declare const emoveCommand: Command;
|
|
12
|
+
export default emoveCommand;
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Husky Biz Emove Command
|
|
3
|
+
*
|
|
4
|
+
* Manages emovedistribution.com (B2B e-mobility parts supplier) via web scraping
|
|
5
|
+
* WooCommerce platform integration (Spanish locale)
|
|
6
|
+
* - Parts search and catalog browsing
|
|
7
|
+
* - Order history and details
|
|
8
|
+
* - Invoice download
|
|
9
|
+
*/
|
|
10
|
+
import { Command } from "commander";
|
|
11
|
+
import { EmovePlaywrightClient } from "../../lib/biz/emove-playwright.js";
|
|
12
|
+
import { getConfig, saveConfig } from "../config.js";
|
|
13
|
+
import * as path from "path";
|
|
14
|
+
import { homedir } from "os";
|
|
15
|
+
export const emoveCommand = new Command("emove")
|
|
16
|
+
.description("Manage emovedistribution.com (e-mobility parts supplier - WooCommerce/ES)");
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// husky biz emove login
|
|
19
|
+
// ============================================================================
|
|
20
|
+
emoveCommand
|
|
21
|
+
.command("login")
|
|
22
|
+
.description("Setup Emove credentials")
|
|
23
|
+
.requiredOption("-u, --username <username>", "Login username or email")
|
|
24
|
+
.requiredOption("-p, --password <password>", "Login password")
|
|
25
|
+
.option("--base-url <url>", "Base URL", "https://emovedistribution.com")
|
|
26
|
+
.action(async (options) => {
|
|
27
|
+
try {
|
|
28
|
+
// Save to config
|
|
29
|
+
const config = getConfig();
|
|
30
|
+
config.emoveUsername = options.username;
|
|
31
|
+
config.emovePassword = options.password;
|
|
32
|
+
if (options.baseUrl) {
|
|
33
|
+
config.emoveBaseUrl = options.baseUrl;
|
|
34
|
+
}
|
|
35
|
+
saveConfig(config);
|
|
36
|
+
console.log("Testing authentication...");
|
|
37
|
+
// Test login
|
|
38
|
+
const client = EmovePlaywrightClient.fromConfig();
|
|
39
|
+
try {
|
|
40
|
+
const result = await client.login();
|
|
41
|
+
if (result.success) {
|
|
42
|
+
console.log("✓ Successfully authenticated with emovedistribution.com");
|
|
43
|
+
console.log("\nYou can now use:");
|
|
44
|
+
console.log(" husky biz emove orders list");
|
|
45
|
+
console.log(" husky biz emove orders get <id>");
|
|
46
|
+
console.log(" husky biz emove invoice <order-id>");
|
|
47
|
+
console.log(" husky biz emove products <query>");
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
console.error("✗ Login failed:", result.error);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
await client.close();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
console.error("✗ Login failed:", error.message);
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
// ============================================================================
|
|
64
|
+
// husky biz emove orders
|
|
65
|
+
// ============================================================================
|
|
66
|
+
const ordersSubcommand = new Command("orders")
|
|
67
|
+
.description("View supplier orders");
|
|
68
|
+
ordersSubcommand
|
|
69
|
+
.command("list")
|
|
70
|
+
.description("List all orders from Emove")
|
|
71
|
+
.option("--json", "Output as JSON")
|
|
72
|
+
.action(async (options) => {
|
|
73
|
+
const client = EmovePlaywrightClient.fromConfig();
|
|
74
|
+
try {
|
|
75
|
+
const orders = await client.listOrders();
|
|
76
|
+
if (options.json) {
|
|
77
|
+
console.log(JSON.stringify(orders, null, 2));
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (orders.length === 0) {
|
|
81
|
+
console.log("\n No orders found.\n");
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
console.log(`\n 📦 Emove Orders (${orders.length} found)\n`);
|
|
85
|
+
// Header
|
|
86
|
+
console.log(` ${"Order #".padEnd(15)} │ ` +
|
|
87
|
+
`${"Date".padEnd(20)} │ ` +
|
|
88
|
+
`${"Status".padEnd(15)} │ ` +
|
|
89
|
+
`${"Total".padEnd(12)}`);
|
|
90
|
+
console.log(" " + "─".repeat(75));
|
|
91
|
+
// Orders
|
|
92
|
+
for (const order of orders) {
|
|
93
|
+
console.log(` ${order.orderNumber.padEnd(15)} │ ` +
|
|
94
|
+
`${order.date.padEnd(20)} │ ` +
|
|
95
|
+
`${order.status.padEnd(15)} │ ` +
|
|
96
|
+
`${order.total || 'N/A'}`);
|
|
97
|
+
}
|
|
98
|
+
console.log("");
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
console.error("Error:", error.message);
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
finally {
|
|
105
|
+
await client.close();
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
ordersSubcommand
|
|
109
|
+
.command("get <id>")
|
|
110
|
+
.description("Get order details")
|
|
111
|
+
.option("--json", "Output as JSON")
|
|
112
|
+
.action(async (id, options) => {
|
|
113
|
+
const client = EmovePlaywrightClient.fromConfig();
|
|
114
|
+
try {
|
|
115
|
+
const order = await client.getOrder(id);
|
|
116
|
+
if (options.json) {
|
|
117
|
+
console.log(JSON.stringify(order, null, 2));
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
console.log(`\n Order ${order.orderNumber}`);
|
|
121
|
+
console.log(" " + "─".repeat(60));
|
|
122
|
+
console.log(` Status: ${order.status}`);
|
|
123
|
+
console.log(` Date: ${order.date}`);
|
|
124
|
+
console.log(` Total: ${order.total || 'N/A'}`);
|
|
125
|
+
if (order.trackingNumber) {
|
|
126
|
+
console.log(` Tracking: ${order.trackingNumber}`);
|
|
127
|
+
}
|
|
128
|
+
if (order.paymentMethod) {
|
|
129
|
+
console.log(` Payment: ${order.paymentMethod}`);
|
|
130
|
+
}
|
|
131
|
+
if (order.customer && order.customer.name) {
|
|
132
|
+
console.log(`\n Shipping To:`);
|
|
133
|
+
console.log(` ${order.customer.name}`);
|
|
134
|
+
if (order.customer.company) {
|
|
135
|
+
console.log(` ${order.customer.company}`);
|
|
136
|
+
}
|
|
137
|
+
if (order.customer.address) {
|
|
138
|
+
console.log(` ${order.customer.address}`);
|
|
139
|
+
}
|
|
140
|
+
if (order.customer.postcode && order.customer.city) {
|
|
141
|
+
console.log(` ${order.customer.postcode} ${order.customer.city}`);
|
|
142
|
+
}
|
|
143
|
+
if (order.customer.email) {
|
|
144
|
+
console.log(` ${order.customer.email}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (order.items.length > 0) {
|
|
148
|
+
console.log(`\n Items:`);
|
|
149
|
+
for (const item of order.items) {
|
|
150
|
+
const sku = item.sku ? `[${item.sku}]`.padEnd(18) : "".padEnd(18);
|
|
151
|
+
const name = item.name.slice(0, 35).padEnd(35);
|
|
152
|
+
console.log(` ${item.quantity}x ${sku} ${name} (${item.total})`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (order.subtotal || order.shipping || order.tax) {
|
|
156
|
+
console.log(`\n Totals:`);
|
|
157
|
+
if (order.subtotal)
|
|
158
|
+
console.log(` Subtotal: ${order.subtotal}`);
|
|
159
|
+
if (order.shipping)
|
|
160
|
+
console.log(` Shipping: ${order.shipping}`);
|
|
161
|
+
if (order.tax)
|
|
162
|
+
console.log(` Tax: ${order.tax}`);
|
|
163
|
+
if (order.total)
|
|
164
|
+
console.log(` Total: ${order.total}`);
|
|
165
|
+
}
|
|
166
|
+
if (order.invoiceUrl) {
|
|
167
|
+
console.log(`\n 📄 Invoice available`);
|
|
168
|
+
console.log(` Download with: husky biz emove invoice ${order.id}`);
|
|
169
|
+
}
|
|
170
|
+
console.log("");
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
console.error("Error:", error.message);
|
|
174
|
+
process.exit(1);
|
|
175
|
+
}
|
|
176
|
+
finally {
|
|
177
|
+
await client.close();
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
emoveCommand.addCommand(ordersSubcommand);
|
|
181
|
+
// ============================================================================
|
|
182
|
+
// husky biz emove invoice
|
|
183
|
+
// ============================================================================
|
|
184
|
+
emoveCommand
|
|
185
|
+
.command("invoice <order-id>")
|
|
186
|
+
.description("Download invoice PDF for order")
|
|
187
|
+
.option("-o, --output <path>", "Save path (default: ~/Downloads/emove-invoice-{id}.pdf)")
|
|
188
|
+
.action(async (orderId, options) => {
|
|
189
|
+
const client = EmovePlaywrightClient.fromConfig();
|
|
190
|
+
try {
|
|
191
|
+
const savePath = options.output ||
|
|
192
|
+
path.join(homedir(), 'Downloads', `emove-invoice-${orderId}.pdf`);
|
|
193
|
+
console.log(`Downloading invoice for order #${orderId}...`);
|
|
194
|
+
const success = await client.downloadInvoice(orderId, savePath);
|
|
195
|
+
if (success) {
|
|
196
|
+
console.log(`✓ Invoice saved to: ${savePath}`);
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
console.error("✗ Invoice not available for this order");
|
|
200
|
+
process.exit(1);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
console.error("Error:", error.message);
|
|
205
|
+
process.exit(1);
|
|
206
|
+
}
|
|
207
|
+
finally {
|
|
208
|
+
await client.close();
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
// ============================================================================
|
|
212
|
+
// husky biz emove products
|
|
213
|
+
// ============================================================================
|
|
214
|
+
emoveCommand
|
|
215
|
+
.command("products <query>")
|
|
216
|
+
.description("Search for parts in catalog")
|
|
217
|
+
.option("--json", "Output as JSON")
|
|
218
|
+
.action(async (query, options) => {
|
|
219
|
+
const client = EmovePlaywrightClient.fromConfig();
|
|
220
|
+
try {
|
|
221
|
+
const products = await client.searchProducts(query);
|
|
222
|
+
if (options.json) {
|
|
223
|
+
console.log(JSON.stringify(products, null, 2));
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
if (products.length === 0) {
|
|
227
|
+
console.log(`\n No products found for: "${query}"\n`);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
console.log(`\n 🔍 Search results for: "${query}" (${products.length} found)\n`);
|
|
231
|
+
for (const product of products) {
|
|
232
|
+
const sku = product.sku ? `[${product.sku}]` : '';
|
|
233
|
+
const price = product.price || 'Price hidden (login required)';
|
|
234
|
+
const stock = product.stockStatus || '';
|
|
235
|
+
console.log(` ${product.name}`);
|
|
236
|
+
console.log(` ${sku} ${price}${stock ? ' - ' + stock : ''}`);
|
|
237
|
+
console.log(` ${product.url}`);
|
|
238
|
+
console.log("");
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
catch (error) {
|
|
242
|
+
console.error("Error:", error.message);
|
|
243
|
+
process.exit(1);
|
|
244
|
+
}
|
|
245
|
+
finally {
|
|
246
|
+
await client.close();
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
export default emoveCommand;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Husky Biz Skuterzone Command
|
|
3
|
+
*
|
|
4
|
+
* Manages skuterzonepro.com (B2B e-mobility parts supplier) via web scraping
|
|
5
|
+
* WooCommerce platform integration
|
|
6
|
+
* - Parts search and catalog browsing
|
|
7
|
+
* - Order history and details
|
|
8
|
+
* - Invoice download
|
|
9
|
+
*/
|
|
10
|
+
import { Command } from "commander";
|
|
11
|
+
export declare const skuterzoneCommand: Command;
|
|
12
|
+
export default skuterzoneCommand;
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Husky Biz Skuterzone Command
|
|
3
|
+
*
|
|
4
|
+
* Manages skuterzonepro.com (B2B e-mobility parts supplier) via web scraping
|
|
5
|
+
* WooCommerce platform integration
|
|
6
|
+
* - Parts search and catalog browsing
|
|
7
|
+
* - Order history and details
|
|
8
|
+
* - Invoice download
|
|
9
|
+
*/
|
|
10
|
+
import { Command } from "commander";
|
|
11
|
+
import { SkuterzonePlaywrightClient } from "../../lib/biz/skuterzone-playwright.js";
|
|
12
|
+
import { getConfig, saveConfig } from "../config.js";
|
|
13
|
+
import * as path from "path";
|
|
14
|
+
import { homedir } from "os";
|
|
15
|
+
export const skuterzoneCommand = new Command("skuterzone")
|
|
16
|
+
.description("Manage skuterzonepro.com (e-mobility parts supplier - WooCommerce)");
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// husky biz skuterzone login
|
|
19
|
+
// ============================================================================
|
|
20
|
+
skuterzoneCommand
|
|
21
|
+
.command("login")
|
|
22
|
+
.description("Setup Skuterzone credentials")
|
|
23
|
+
.requiredOption("-u, --username <username>", "Login username or email")
|
|
24
|
+
.requiredOption("-p, --password <password>", "Login password")
|
|
25
|
+
.option("--base-url <url>", "Base URL", "https://skuterzonepro.com")
|
|
26
|
+
.action(async (options) => {
|
|
27
|
+
try {
|
|
28
|
+
// Save to config
|
|
29
|
+
const config = getConfig();
|
|
30
|
+
config.skuterzoneUsername = options.username;
|
|
31
|
+
config.skuterzonePassword = options.password;
|
|
32
|
+
if (options.baseUrl) {
|
|
33
|
+
config.skuterzoneBaseUrl = options.baseUrl;
|
|
34
|
+
}
|
|
35
|
+
saveConfig(config);
|
|
36
|
+
console.log("Testing authentication...");
|
|
37
|
+
// Test login
|
|
38
|
+
const client = SkuterzonePlaywrightClient.fromConfig();
|
|
39
|
+
try {
|
|
40
|
+
const result = await client.login();
|
|
41
|
+
if (result.success) {
|
|
42
|
+
console.log("✓ Successfully authenticated with skuterzonepro.com");
|
|
43
|
+
console.log("\nYou can now use:");
|
|
44
|
+
console.log(" husky biz skuterzone orders list");
|
|
45
|
+
console.log(" husky biz skuterzone orders get <id>");
|
|
46
|
+
console.log(" husky biz skuterzone invoice <order-id>");
|
|
47
|
+
console.log(" husky biz skuterzone products <query>");
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
console.error("✗ Login failed:", result.error);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
await client.close();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
console.error("✗ Login failed:", error.message);
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
// ============================================================================
|
|
64
|
+
// husky biz skuterzone orders
|
|
65
|
+
// ============================================================================
|
|
66
|
+
const ordersSubcommand = new Command("orders")
|
|
67
|
+
.description("View supplier orders");
|
|
68
|
+
ordersSubcommand
|
|
69
|
+
.command("list")
|
|
70
|
+
.description("List all orders from Skuterzone")
|
|
71
|
+
.option("--json", "Output as JSON")
|
|
72
|
+
.action(async (options) => {
|
|
73
|
+
const client = SkuterzonePlaywrightClient.fromConfig();
|
|
74
|
+
try {
|
|
75
|
+
const orders = await client.listOrders();
|
|
76
|
+
if (options.json) {
|
|
77
|
+
console.log(JSON.stringify(orders, null, 2));
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (orders.length === 0) {
|
|
81
|
+
console.log("\n No orders found.\n");
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
console.log(`\n 📦 Skuterzone Orders (${orders.length} found)\n`);
|
|
85
|
+
// Header
|
|
86
|
+
console.log(` ${"Order #".padEnd(15)} │ ` +
|
|
87
|
+
`${"Date".padEnd(20)} │ ` +
|
|
88
|
+
`${"Status".padEnd(15)} │ ` +
|
|
89
|
+
`${"Total".padEnd(12)}`);
|
|
90
|
+
console.log(" " + "─".repeat(75));
|
|
91
|
+
// Orders
|
|
92
|
+
for (const order of orders) {
|
|
93
|
+
console.log(` ${order.orderNumber.padEnd(15)} │ ` +
|
|
94
|
+
`${order.date.padEnd(20)} │ ` +
|
|
95
|
+
`${order.status.padEnd(15)} │ ` +
|
|
96
|
+
`${order.total}`);
|
|
97
|
+
}
|
|
98
|
+
console.log("");
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
console.error("Error:", error.message);
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
finally {
|
|
105
|
+
await client.close();
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
ordersSubcommand
|
|
109
|
+
.command("get <id>")
|
|
110
|
+
.description("Get order details")
|
|
111
|
+
.option("--json", "Output as JSON")
|
|
112
|
+
.action(async (id, options) => {
|
|
113
|
+
const client = SkuterzonePlaywrightClient.fromConfig();
|
|
114
|
+
try {
|
|
115
|
+
const order = await client.getOrder(id);
|
|
116
|
+
if (options.json) {
|
|
117
|
+
console.log(JSON.stringify(order, null, 2));
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
console.log(`\n Order ${order.orderNumber}`);
|
|
121
|
+
console.log(" " + "─".repeat(60));
|
|
122
|
+
console.log(` Status: ${order.status}`);
|
|
123
|
+
console.log(` Date: ${order.date}`);
|
|
124
|
+
console.log(` Total: ${order.total}`);
|
|
125
|
+
if (order.trackingNumber) {
|
|
126
|
+
console.log(` Tracking: ${order.trackingNumber}`);
|
|
127
|
+
}
|
|
128
|
+
if (order.paymentMethod) {
|
|
129
|
+
console.log(` Payment: ${order.paymentMethod}`);
|
|
130
|
+
}
|
|
131
|
+
if (order.customer && order.customer.name) {
|
|
132
|
+
console.log(`\n Shipping To:`);
|
|
133
|
+
console.log(` ${order.customer.name}`);
|
|
134
|
+
if (order.customer.company) {
|
|
135
|
+
console.log(` ${order.customer.company}`);
|
|
136
|
+
}
|
|
137
|
+
if (order.customer.address) {
|
|
138
|
+
console.log(` ${order.customer.address}`);
|
|
139
|
+
}
|
|
140
|
+
if (order.customer.postcode && order.customer.city) {
|
|
141
|
+
console.log(` ${order.customer.postcode} ${order.customer.city}`);
|
|
142
|
+
}
|
|
143
|
+
if (order.customer.email) {
|
|
144
|
+
console.log(` ${order.customer.email}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (order.items.length > 0) {
|
|
148
|
+
console.log(`\n Items:`);
|
|
149
|
+
for (const item of order.items) {
|
|
150
|
+
const sku = item.sku ? `[${item.sku}]`.padEnd(18) : "".padEnd(18);
|
|
151
|
+
const name = item.name.slice(0, 35).padEnd(35);
|
|
152
|
+
console.log(` ${item.quantity}x ${sku} ${name} (${item.total})`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (order.subtotal || order.shipping || order.tax) {
|
|
156
|
+
console.log(`\n Totals:`);
|
|
157
|
+
if (order.subtotal)
|
|
158
|
+
console.log(` Subtotal: ${order.subtotal}`);
|
|
159
|
+
if (order.shipping)
|
|
160
|
+
console.log(` Shipping: ${order.shipping}`);
|
|
161
|
+
if (order.tax)
|
|
162
|
+
console.log(` Tax: ${order.tax}`);
|
|
163
|
+
console.log(` Total: ${order.total}`);
|
|
164
|
+
}
|
|
165
|
+
if (order.invoiceUrl) {
|
|
166
|
+
console.log(`\n 📄 Invoice available`);
|
|
167
|
+
console.log(` Download with: husky biz skuterzone invoice ${order.id}`);
|
|
168
|
+
}
|
|
169
|
+
console.log("");
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
console.error("Error:", error.message);
|
|
173
|
+
process.exit(1);
|
|
174
|
+
}
|
|
175
|
+
finally {
|
|
176
|
+
await client.close();
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
skuterzoneCommand.addCommand(ordersSubcommand);
|
|
180
|
+
// ============================================================================
|
|
181
|
+
// husky biz skuterzone invoice
|
|
182
|
+
// ============================================================================
|
|
183
|
+
skuterzoneCommand
|
|
184
|
+
.command("invoice <order-id>")
|
|
185
|
+
.description("Download invoice PDF for order")
|
|
186
|
+
.option("-o, --output <path>", "Save path (default: ~/Downloads/skuterzone-invoice-{id}.pdf)")
|
|
187
|
+
.action(async (orderId, options) => {
|
|
188
|
+
const client = SkuterzonePlaywrightClient.fromConfig();
|
|
189
|
+
try {
|
|
190
|
+
const savePath = options.output ||
|
|
191
|
+
path.join(homedir(), 'Downloads', `skuterzone-invoice-${orderId}.pdf`);
|
|
192
|
+
console.log(`Downloading invoice for order #${orderId}...`);
|
|
193
|
+
const success = await client.downloadInvoice(orderId, savePath);
|
|
194
|
+
if (success) {
|
|
195
|
+
console.log(`✓ Invoice saved to: ${savePath}`);
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
console.error("✗ Invoice not available for this order");
|
|
199
|
+
process.exit(1);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
catch (error) {
|
|
203
|
+
console.error("Error:", error.message);
|
|
204
|
+
process.exit(1);
|
|
205
|
+
}
|
|
206
|
+
finally {
|
|
207
|
+
await client.close();
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
// ============================================================================
|
|
211
|
+
// husky biz skuterzone products
|
|
212
|
+
// ============================================================================
|
|
213
|
+
skuterzoneCommand
|
|
214
|
+
.command("products <query>")
|
|
215
|
+
.description("Search for parts in catalog")
|
|
216
|
+
.option("--json", "Output as JSON")
|
|
217
|
+
.action(async (query, options) => {
|
|
218
|
+
const client = SkuterzonePlaywrightClient.fromConfig();
|
|
219
|
+
try {
|
|
220
|
+
const products = await client.searchProducts(query);
|
|
221
|
+
if (options.json) {
|
|
222
|
+
console.log(JSON.stringify(products, null, 2));
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
if (products.length === 0) {
|
|
226
|
+
console.log(`\n No products found for: "${query}"\n`);
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
console.log(`\n 🔍 Search results for: "${query}" (${products.length} found)\n`);
|
|
230
|
+
for (const product of products) {
|
|
231
|
+
const sku = product.sku ? `[${product.sku}]` : '';
|
|
232
|
+
const price = product.price || 'Price hidden (login required)';
|
|
233
|
+
const stock = product.stockStatus || '';
|
|
234
|
+
console.log(` ${product.name}`);
|
|
235
|
+
console.log(` ${sku} ${price}${stock ? ' - ' + stock : ''}`);
|
|
236
|
+
console.log(` ${product.url}`);
|
|
237
|
+
console.log("");
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
catch (error) {
|
|
241
|
+
console.error("Error:", error.message);
|
|
242
|
+
process.exit(1);
|
|
243
|
+
}
|
|
244
|
+
finally {
|
|
245
|
+
await client.close();
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
export default skuterzoneCommand;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Husky Biz Wattiz Command
|
|
3
|
+
*
|
|
4
|
+
* Manages wattiz.fr (B2B e-mobility parts supplier) via web scraping
|
|
5
|
+
* PrestaShop platform integration
|
|
6
|
+
* - Parts search and catalog browsing
|
|
7
|
+
* - Order history and details
|
|
8
|
+
* - Invoice download
|
|
9
|
+
*/
|
|
10
|
+
import { Command } from "commander";
|
|
11
|
+
export declare const wattizCommand: Command;
|
|
12
|
+
export default wattizCommand;
|