cyymall-cli 0.1.11 → 0.1.12
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/package.json +2 -2
- package/src/cartProduct.js +90 -0
- package/src/commands/order.js +21 -7
- package/src/Untitled +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cyymall-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.12",
|
|
4
4
|
"description": "CyyMall / 菜洋洋商城 API CLI (per app-api-cli-spec)",
|
|
5
5
|
"bin": {
|
|
6
6
|
"cyy": "bin/cyy.js"
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"scripts": {
|
|
20
20
|
"start": "node bin/cyy.js",
|
|
21
21
|
"lint": "node --check src/cli.js && node --check src/encrypt.js && node --check src/embeddedCyyKeys.js",
|
|
22
|
-
"prepublishOnly": "node --check src/cli.js && node --check src/encrypt.js && node --check src/embeddedCyyKeys.js && node --check bin/cyy.js"
|
|
22
|
+
"prepublishOnly": "node --check src/cli.js && node --check src/cartProduct.js && node --check src/encrypt.js && node --check src/embeddedCyyKeys.js && node --check bin/cyy.js"
|
|
23
23
|
},
|
|
24
24
|
"keywords": [
|
|
25
25
|
"cyymall",
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const http = require("./http");
|
|
4
|
+
const biz = require("./biz");
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Search getSkuList; pick first hit; resolve price/unit from promotionList (matches `quick`/`checkout`).
|
|
8
|
+
* @param {Record<string, unknown>} cfg
|
|
9
|
+
* @param {{ keyword: string, shopId: number, siteId: number, quantity: number, unit: string }} opts
|
|
10
|
+
*/
|
|
11
|
+
async function resolveProductLine(cfg, opts) {
|
|
12
|
+
const { keyword, shopId, siteId, quantity, unit } = opts;
|
|
13
|
+
const headers = /** @type {Record<string,string>} */ (http.buildAuthHeaders(cfg));
|
|
14
|
+
|
|
15
|
+
const searchUrl = http.moduleUrl("PRODUCT", "/app/product/getSkuList");
|
|
16
|
+
const searchBody = JSON.stringify({
|
|
17
|
+
pageNum: 1,
|
|
18
|
+
pageSize: 10,
|
|
19
|
+
shopId,
|
|
20
|
+
siteId,
|
|
21
|
+
spuName: keyword,
|
|
22
|
+
stockFlag: "0",
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const r = await http.request(searchUrl, {
|
|
26
|
+
method: "POST",
|
|
27
|
+
headers,
|
|
28
|
+
body: searchBody,
|
|
29
|
+
});
|
|
30
|
+
if (!r.ok || !biz.isBizSuccess(r.json)) {
|
|
31
|
+
/** @type {Error & { cause?: unknown }} */
|
|
32
|
+
const err = new Error(`search failed for "${keyword}"`);
|
|
33
|
+
err.cause = r.json;
|
|
34
|
+
throw err;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const list =
|
|
38
|
+
r.json &&
|
|
39
|
+
typeof r.json === "object" &&
|
|
40
|
+
r.json.data &&
|
|
41
|
+
typeof r.json.data === "object"
|
|
42
|
+
? /** @type {{ list?: unknown[] }} */ (r.json.data).list
|
|
43
|
+
: [];
|
|
44
|
+
const products = Array.isArray(list) ? list : [];
|
|
45
|
+
if (!products.length) {
|
|
46
|
+
throw new Error(`no products found for "${keyword}"`);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const product = /** @type {Record<string, unknown>} */ (products[0]);
|
|
50
|
+
const skuId = Number(product.id);
|
|
51
|
+
const skuCode = String(product.skuCode || "");
|
|
52
|
+
const skuName = String(product.spuName || "");
|
|
53
|
+
const stockQty = Number(product.stockAllQuantity ?? 0);
|
|
54
|
+
const promotionList = Array.isArray(product.promotionList) ? product.promotionList : [];
|
|
55
|
+
|
|
56
|
+
let price = 0;
|
|
57
|
+
let unitRate = 1;
|
|
58
|
+
let skuSaleUnit = unit;
|
|
59
|
+
for (const p of promotionList) {
|
|
60
|
+
const row = /** @type {Record<string, unknown>} */ (p);
|
|
61
|
+
if (row.skuSaleUnitName === unit) {
|
|
62
|
+
price = Number(row.salePrice || 0);
|
|
63
|
+
unitRate = Number(row.unitRate ?? 1);
|
|
64
|
+
skuSaleUnit = String(row.skuSaleUnitName || unit);
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (!price) {
|
|
69
|
+
const availableUnits = promotionList.map(
|
|
70
|
+
(x) => /** @type {{ skuSaleUnitName?: string }} */ (x).skuSaleUnitName,
|
|
71
|
+
);
|
|
72
|
+
const err = new Error(`unit "${unit}" not found in promotionList for "${keyword}"`);
|
|
73
|
+
/** @type {Error & { availableUnits?: (string | undefined)[] }} */ (err).availableUnits = availableUnits;
|
|
74
|
+
throw err;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
skuId,
|
|
79
|
+
skuCode,
|
|
80
|
+
skuName,
|
|
81
|
+
skuQty: quantity,
|
|
82
|
+
skuSaleUnit,
|
|
83
|
+
listPrice: price,
|
|
84
|
+
salePrice: price,
|
|
85
|
+
unitRate,
|
|
86
|
+
stockQty,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
module.exports = { resolveProductLine };
|
package/src/commands/order.js
CHANGED
|
@@ -406,13 +406,27 @@ async function checkout(opts) {
|
|
|
406
406
|
for (const spec of itemSpecs) {
|
|
407
407
|
const kw = spec.keyword;
|
|
408
408
|
if (!kw) continue;
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
409
|
+
let line;
|
|
410
|
+
try {
|
|
411
|
+
line = await resolveProductLine(cfg, {
|
|
412
|
+
keyword: kw,
|
|
413
|
+
shopId,
|
|
414
|
+
siteId,
|
|
415
|
+
quantity: Number(spec.quantity ?? quantity),
|
|
416
|
+
unit: String(spec.unit ?? unit),
|
|
417
|
+
});
|
|
418
|
+
} catch (e) {
|
|
419
|
+
const msg = /** @type {Error & { cause?: unknown, availableUnits?: unknown }} */ (
|
|
420
|
+
typeof e === "object" && e !== null ? e : { message: String(e) }
|
|
421
|
+
);
|
|
422
|
+
envelope(
|
|
423
|
+
false,
|
|
424
|
+
msg.message || String(e),
|
|
425
|
+
{ keyword: kw, upstream: msg.cause, availableUnits: msg.availableUnits },
|
|
426
|
+
2,
|
|
427
|
+
);
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
416
430
|
lines.push(line);
|
|
417
431
|
cartItemList.push({
|
|
418
432
|
skuCode: line.skuCode,
|
package/src/Untitled
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
shop
|