@optima-chat/tiktok-cli 0.15.1 → 0.16.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/README.md +3 -0
- package/dist/index.js +364 -67
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,6 +26,7 @@ tiktok <domain> <verb> --shop <shopId> [--flags]
|
|
|
26
26
|
| `analytics products` | 商品维度数据(GMV 降序)。`--version` 默认 `202509`;`202605` 返回 `total_performance` + 分渠道 `*_performance` 组(**组是可选的、字段名三套变体、`overall_performance` 在新版不存在**,见 spec §3.0);未知版本本地拒,平台出新版可 `--force-version` 直接试;`--page-token` 翻页,**末页 `next_page_token` 为空串**(不是缺席) |
|
|
27
27
|
| `products list` | 商品列表 |
|
|
28
28
|
| `promotions list` | 促销活动。`--status` **省略 = 全部状态**(`ONGOING`/`NOT_START`/`EXPIRED`/`DEACTIVATED`;⚠️ 值写错平台**静默忽略并返回全部**,故 CLI **本地硬拒未知值**;平台将来新增值可用 `--force-status` 越过);`--page-size`(默认 20);`--page-token` 翻页,**末页无 `next_page_token`** |
|
|
29
|
+
| `promotions get` | 按 id 读单个促销活动(`--id`):类型、状态、时间窗、挂的商品与每个 SKU 的活动价(一口价 / 秒杀价读 `skus[].activity_price.amount`,百分比读 `skus[].discount`)。平台没回 `products` 时补成 `[]` |
|
|
29
30
|
| `finance statements` | 结算单 |
|
|
30
31
|
|
|
31
32
|
### 建品前置只读辅助(拼商品体用)
|
|
@@ -96,6 +97,8 @@ tiktok products set-price --shop <id> --product <pid> --sku <sid> --price 29.90
|
|
|
96
97
|
| `products set-price` | 改 SKU 售价(`--product --sku --price [--currency]`)。仅 `ACTIVATE` 商品,且不在进行中的促销里(`update-price-202309` 原文)。改价不触发商品重审、立即生效(依据是 `partial-edit-product-202309` 的「`price`/`inventory` 不需 reaudit」,**本端点自己的文档没写这句、也未单独实测**)。 | ✓ 改价+回读 |
|
|
97
98
|
| `products set-inventory` | 改 SKU 库存(`--product --sku --warehouse --quantity`)。只要商品不在 `FREEZE`/`DELETED` 状态都能改(`update-inventory-202309` 原文)。改库存不触发商品重审、立即生效(同上依据,未单独实测)。⚠️ `DRAFT` 商品**未实测** —— 官方只写了「非 `FREEZE`/`DELETED`」,没说 DRAFT 可以;且草稿 SKU 常常还没分仓,会撞 `12052096`。 | ✓ 49→55→49 可逆 |
|
|
98
99
|
| `promotions create-flashsale` | 建秒杀(`--title --product --sku --price [--limit --per-user --hours]`)。两步:建壳+加品 | ✓ 真实建成 |
|
|
100
|
+
| `promotions create-discount` | 建商品折扣活动:`--price` 一口价(`FIXED_PRICE`)或 `--percent` 减 N%(`DIRECT_DISCOUNT`;`85` = 减 85%、按原价 15% 卖,**打 85 折要传 15**),`--title [--product] [--days 180]`。两步:建壳+加品,可多商品;撞重名 / 加品失败时给可粘贴的下一步命令 | ✓ 真实建成(FP;--percent 待活体) |
|
|
101
|
+
| `promotions add-products` | 往已有折扣活动加新 SKU(`--id <activityId> --price|--percent … [--product]`)。预读先于 PUT:类型 / 状态 / 已在活动里的 SKU 都会被拦下;只加不改 | — |
|
|
99
102
|
| `promotions deactivate` | 终止促销活动(`--id`)。不可逆 | ✓ |
|
|
100
103
|
| `products create --body-file <json>` | **生产级建品**(完整商品体 JSON)。dry-run 内嵌 `listing_check` 预检 → `--apply` 建品 → 回读高亮 warnings。⚠️ `save_mode` 默认 `LISTING`:**不写就是建完直接上架送审**(#1958,见下方「送审语义」)。可在 body 里写 `"save_mode": "AS_DRAFT"` 留草稿(**未实测**)。 | ✓ 真实上架 V.V.Love(ACTIVATE) |
|
|
101
104
|
| `products add-variant --product <id> --body-file <json>` | 加规格 SKU(读现有 skus → merge → partial_edit;新 SKU 自动继承 sku_dimensions/sku_weight)。⚠️ **默认送审**(#1958,见下方「送审语义」)。本命令**自构 body**,body-file 里的 `save_mode` **不透传、写了也无效**;要留草稿只能用 `products partial-edit`。 | ✓ 真加变体成功 |
|
package/dist/index.js
CHANGED
|
@@ -310,11 +310,12 @@ function commandUsage(cmd) {
|
|
|
310
310
|
const flags = cmd.flags?.length ? cmd.flags.map((f) => `--${f}`).join(" ") : "\uFF08\u6CA1\u6709\u4E13\u5C5E\u53C2\u6570\uFF09";
|
|
311
311
|
const shop = cmd.noShop ? "" : " --shop <shopId>";
|
|
312
312
|
const globals = cmd.noShop ? "--apply" : "--shop / --apply";
|
|
313
|
+
const dry = cmd.write ? "\u672C\u547D\u4EE4\u662F\u5199\u64CD\u4F5C\uFF1A\u9ED8\u8BA4 dry-run\uFF08\u53EA\u6253\u5370\u5C06\u53D1\u7684\u8BF7\u6C42\u3001\u4E0D\u53D1\uFF09\uFF0C\u52A0 --apply \u624D\u771F\u53D1\u3002\n" : "";
|
|
313
314
|
return `tiktok ${cmd.name}${shop} [--flags]
|
|
314
315
|
|
|
315
316
|
${cmd.summary}
|
|
316
317
|
|
|
317
|
-
\u8BA4\u7684\u53C2\u6570\uFF1A${flags}\uFF08\u53E6\u6709\u5168\u5C40 ${globals}\uFF09\uFF1B\u4E0D\u8BA4\u7684\u4F1A\u5F53\u573A\u62A5\u9519\u3002
|
|
318
|
+
${dry}\u8BA4\u7684\u53C2\u6570\uFF1A${flags}\uFF08\u53E6\u6709\u5168\u5C40 ${globals}\uFF09\uFF1B\u4E0D\u8BA4\u7684\u4F1A\u5F53\u573A\u62A5\u9519\u3002
|
|
318
319
|
`;
|
|
319
320
|
}
|
|
320
321
|
var today = () => (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
@@ -322,6 +323,37 @@ var daysAgo = (n) => new Date(Date.now() - n * 864e5).toISOString().slice(0, 10)
|
|
|
322
323
|
var toEpoch = (v) => /^\d+$/.test(v) ? Number(v) : Math.floor(Date.parse(v) / 1e3);
|
|
323
324
|
var PROMOTION_STATUSES = /* @__PURE__ */ new Set(["ONGOING", "NOT_START", "EXPIRED", "DEACTIVATED"]);
|
|
324
325
|
var ANALYTICS_PRODUCT_VERSIONS = /* @__PURE__ */ new Set(["202509", "202605"]);
|
|
326
|
+
var ADD_TEXT = {
|
|
327
|
+
SUM_ADD: "\u5F80\u5DF2\u6709\u6298\u6263\u6D3B\u52A8\u52A0\u65B0 SKU\uFF08--id <activityId> --price <skuId>:<\u4E00\u53E3\u4EF7>|<productId>/<skuId>:<\u4E00\u53E3\u4EF7>[,...] \u6216 --percent <skuId>:<\u51CFN%>[,...] [--product]\uFF09\u3002\u5148\u8BFB\u6D3B\u52A8\u6838\u5BF9\u7C7B\u578B\u4E0E\u5DF2\u6709 SKU \u518D\u52A0\u54C1\u3001\u56DE\u8BFB\uFF1B\u53EA\u52A0\u4E0D\u6539\uFF0C\u5DF2\u5728\u6D3B\u52A8\u91CC\u7684 SKU \u4F1A\u88AB\u62E6\u4E0B\u3002--percent 85 = \u51CF85%\uFF08\u625385\u6298\u8981\u4F2015\uFF09",
|
|
328
|
+
SUM_GET: "\u6309 id \u8BFB\u5355\u4E2A\u4FC3\u9500\u6D3B\u52A8\uFF08--id <activityId>\uFF09\uFF1A\u7C7B\u578B\u3001\u72B6\u6001\u3001\u65F6\u95F4\u7A97\u3001\u6302\u7684\u5546\u54C1\u4E0E\u6BCF\u4E2A SKU \u7684\u6D3B\u52A8\u4EF7\uFF08\u4E00\u53E3\u4EF7 / \u79D2\u6740\u4EF7\u8BFB skus[].activity_price.amount\uFF0C\u767E\u5206\u6BD4\u8BFB skus[].discount\uFF09",
|
|
329
|
+
HUMAN_ADD: (id, list) => `\u5F80\u6D3B\u52A8 ${id} \u52A0\uFF1A${list}\u3002\u53EA\u52A0\u65B0 SKU\uFF1B\u5DF2\u5728\u6D3B\u52A8\u91CC\u7684\u4F1A\u5728 --apply \u9884\u8BFB\u65F6\u88AB\u62E6\u4E0B\u3002`,
|
|
330
|
+
AV2: "\u672C\u547D\u4EE4\u7528 --id \u4F20\u6D3B\u52A8 id\uFF08\u6CA1\u6709 --activity-id\uFF09\uFF0C\u5982 --id 7686081985965900001",
|
|
331
|
+
AV3: (rest, flag) => `\u591A\u4F59\u7684\u4F4D\u7F6E\u53C2\u6570\u300C${rest}\u300D\u2014\u2014\u6BCF\u4E2A\u53C2\u6570\u53EA\u80FD\u5E26\u4E00\u4E2A\u503C\u3002\u591A\u4E2A SKU \u8981\u7528\u9017\u53F7\u8FDE\u6210\u4E00\u4E2A --${flag}\uFF0C\u5982 --${flag} A:12,B:15\uFF08\u4E0D\u80FD\u7528\u7A7A\u683C\u5206\u9694\uFF09`,
|
|
332
|
+
GV3: (rest) => `\u591A\u4F59\u7684\u4F4D\u7F6E\u53C2\u6570\u300C${rest}\u300D\u2014\u2014\u6BCF\u4E2A\u53C2\u6570\u53EA\u80FD\u5E26\u4E00\u4E2A\u503C\u3002`,
|
|
333
|
+
AP1: (shop, id) => `\u6CA1\u8BFB\u5230\u6D3B\u52A8 ${id}\uFF0C\u672A\u52A0\u4EFB\u4F55\u5546\u54C1\uFF1B\u5148\u7528 \`tiktok promotions get --shop ${shop} --id ${id}\` \u786E\u8BA4\u6D3B\u52A8\u5B58\u5728\u3002`,
|
|
334
|
+
AP1N: (id) => `\u8BFB\u53D6\u6D3B\u52A8 ${id} \u5931\u8D25\uFF08\u7F51\u7EDC / \u670D\u52A1\u7AEF\u6682\u65F6\u6027\u9519\u8BEF\uFF09\uFF0C\u672A\u5199\u4EFB\u4F55\u4E1C\u897F\uFF0C\u53EF\u4EE5\u539F\u6837\u91CD\u8DD1\u672C\u547D\u4EE4\u3002`,
|
|
335
|
+
AP1M: (shop, id) => `\u9884\u8BFB\u5230\u7684\u6D3B\u52A8 ${id} \u5F62\u72B6\u5F02\u5E38\uFF08\u7F3A activity_type \u6216 products\uFF09\uFF0C\u672A\u5199\u4EFB\u4F55\u4E1C\u897F\uFF1B\u5148\u7528 \`tiktok promotions get --shop ${shop} --id ${id}\` \u770B\u6D3B\u52A8\u8BE6\u60C5\uFF08\u6CE8\u610F get \u4F1A\u628A\u5E73\u53F0\u6CA1\u56DE\u7684 products \u8865\u6210 []\uFF0C\u8981\u770B\u5E73\u53F0\u539F\u6837\u54CD\u5E94\u5F97\u76F4\u8FDE\uFF09\u3002`,
|
|
336
|
+
AT1: (id) => `\u6D3B\u52A8 ${id} \u662F FIXED_PRICE\uFF08\u4E00\u53E3\u4EF7\uFF09\uFF0C\u8981\u7528 --price <skuId>:<\u4E00\u53E3\u4EF7>\uFF1B--percent \u53EA\u7528\u4E8E DIRECT_DISCOUNT \u6D3B\u52A8\u3002`,
|
|
337
|
+
AT2: (id) => `\u6D3B\u52A8 ${id} \u662F DIRECT_DISCOUNT\uFF08\u767E\u5206\u6BD4\uFF09\uFF0C\u8981\u7528 --percent <skuId>:<\u51CFN%>\uFF1B--price \u53EA\u7528\u4E8E FIXED_PRICE \u6D3B\u52A8\u3002`,
|
|
338
|
+
AT3: (id) => `\u6D3B\u52A8 ${id} \u662F FLASHSALE\uFF08\u79D2\u6740\uFF09\uFF1A\u79D2\u6740\u6D3B\u52A8\u52A0\u54C1\u4E0D\u5728\u672C\u547D\u4EE4\u8303\u56F4\uFF0C\u53E6\u5EFA\u4E00\u573A\u7528 tiktok promotions create-flashsale\u3002`,
|
|
339
|
+
AT4: (id, type) => `\u6D3B\u52A8 ${id} \u7684\u7C7B\u578B\u662F ${type}\uFF0C\u672C\u547D\u4EE4\u53EA\u652F\u6301\u5F80 FIXED_PRICE / DIRECT_DISCOUNT \u6D3B\u52A8\u52A0\u54C1\u3002`,
|
|
340
|
+
AS1: (id, status, allowed) => `\u6D3B\u52A8 ${id} \u7684\u72B6\u6001\u662F ${status}\uFF0C\u53EA\u6709 ${allowed} \u7684\u6D3B\u52A8\u80FD\u7528\u672C\u547D\u4EE4\u52A0\u54C1\u3002`,
|
|
341
|
+
AL1: (id, level) => `\u6D3B\u52A8 ${id} \u7684 product_level \u662F ${level}\uFF0C\u672C\u547D\u4EE4\u53EA\u652F\u6301 VARIATION\uFF08\u6309 SKU \u5B9A\u4EF7\uFF09\u7684\u6D3B\u52A8\u3002`,
|
|
342
|
+
AD1: (id, sids) => `\u8FD9\u4E9B SKU \u5DF2\u5728\u6D3B\u52A8 ${id} \u91CC\u3001\u4F46\u503C\u4E0E\u672C\u6B21\u63D0\u4EA4\u4E0D\u540C\uFF1A${sids}\u3002\u6539\u5DF2\u5728\u6D3B\u52A8\u91CC\u7684 SKU \u7684\u4EF7 / \u6298\u6263\u4E0D\u5728\u672C\u547D\u4EE4\u8303\u56F4\uFF08\u91CD\u590D\u63D0\u4EA4\u7684\u5E73\u53F0\u884C\u4E3A\u672A\u5B9E\u6D4B\uFF09\uFF0C\u4ECD\u8D70\u6D4F\u89C8\u5668\u3002`,
|
|
343
|
+
AD1_REST: (addCmd) => `\u6CA1\u5728\u6D3B\u52A8\u91CC\u7684\u53EF\u4EE5\u8FD9\u6837\u52A0\uFF1A${addCmd}`,
|
|
344
|
+
AD2: (id, sids, addCmd) => `\u8FD9\u4E9B SKU \u5DF2\u6309\u672C\u6B21\u63D0\u4EA4\u7684\u503C\u5728\u6D3B\u52A8 ${id} \u91CC\uFF0C\u65E0\u9700\u518D\u52A0\uFF1A${sids}\u3002\u5176\u4F59\u7684\u8FD9\u6837\u52A0\uFF1A${addCmd}`,
|
|
345
|
+
AD3: (n, id) => `\u672C\u6B21\u63D0\u4EA4\u7684 ${n} \u4E2A SKU \u90FD\u5DF2\u6309\u63D0\u4EA4\u7684\u503C\u5728\u6D3B\u52A8 ${id} \u91CC\u2014\u2014\u65E0\u9700\u518D\u52A0\uFF0C\u522B\u91CD\u8DD1\u3002`,
|
|
346
|
+
AW1: (shop, id) => `\u5DF2\u63D0\u4EA4\u5230\u6D3B\u52A8 ${id}\uFF0C\u4F46\u56DE\u8BFB\u5931\u8D25\uFF0C\u672A\u80FD\u9A8C\u8BC1\u672C\u6B21\u7684 SKU \u662F\u5426\u6302\u4E0A\u2014\u2014\u4E0D\u8981\u91CD\u8DD1\u672C\u547D\u4EE4\uFF1B\u5148\u7528 \`tiktok promotions get --shop ${shop} --id ${id}\` \u6838\u5BF9\uFF0C\u5982\u5B9E\u544A\u8BC9\u5E97\u4E3B\u54EA\u4E9B SKU \u672A\u786E\u8BA4\u6302\u4E0A\u3002`,
|
|
347
|
+
AW2: (id, problems) => `\u5DF2\u63D0\u4EA4\u5230\u6D3B\u52A8 ${id}\uFF0C\u4F46\u56DE\u8BFB\u4E0E\u63D0\u4EA4\u4E0D\u4E00\u81F4\uFF1A${problems}\u2014\u2014\u4E0D\u8981\u91CD\u8DD1\u672C\u547D\u4EE4\uFF1B\u5982\u5B9E\u544A\u8BC9\u5E97\u4E3B\u54EA\u4E9B SKU \u672A\u786E\u8BA4\u6302\u4E0A\u3002`,
|
|
348
|
+
AW2_MISS: (addCmd) => `\u7F3A\u7684\u53EF\u4EE5\u8FD9\u6837\u8865\uFF1A${addCmd}`,
|
|
349
|
+
AW3: (shop, id, lost) => `\u26A0\uFE0F \u6D3B\u52A8 ${id} \u539F\u6709\u7684\u5546\u54C1\u5728\u56DE\u8BFB\u91CC\u5BF9\u4E0D\u4E0A\uFF1A${lost}\u2014\u2014\u52A0\u54C1\u53EF\u80FD\u8986\u76D6\u4E86\u539F\u6709\u5546\u54C1\u3002\u5982\u5B9E\u544A\u8BC9\u5E97\u4E3B\uFF0C\u5E76\u7528 \`tiktok promotions get --shop ${shop} --id ${id}\` \u6838\u5BF9\u3002`,
|
|
350
|
+
AN1: (n, id) => `\u52A0\u5546\u54C1\u62A5\u4E86\u9519\uFF0C\u4F46\u56DE\u8BFB\u663E\u793A\u63D0\u4EA4\u7684 ${n} \u4E2A SKU \u90FD\u5DF2\u6302\u4E0A\u6D3B\u52A8 ${id}\u2014\u2014\u522B\u91CD\u8DD1\u3002`,
|
|
351
|
+
AN2: (id) => `\u52A0\u5546\u54C1\u5931\u8D25\uFF0C\u56DE\u8BFB\u663E\u793A\u672C\u6B21\u63D0\u4EA4\u7684 SKU \u4E00\u4E2A\u90FD\u6CA1\u6302\u4E0A\u6D3B\u52A8 ${id}\u3002\u6309\u4E0A\u9762\u7684\u5E73\u53F0\u62A5\u9519\u6539\u6B63\u53C2\u6570\u540E\u91CD\u8DD1\u672C\u547D\u4EE4\u5373\u53EF\uFF08\u53EA\u6709\u9650\u6D41\u3001\u7F51\u7EDC\u7C7B\u62A5\u9519\u624D\u539F\u6837\u91CD\u8DD1\uFF09\u3002`,
|
|
352
|
+
AN3: (problems) => `\u52A0\u5546\u54C1\u62A5\u4E86\u9519\uFF0C\u56DE\u8BFB\u663E\u793A\u672C\u6B21\u63D0\u4EA4\u7684\u6CA1\u6709\u5168\u90E8\u6302\u4E0A\uFF1A${problems}\u3002`,
|
|
353
|
+
AN3_MISS: (addCmd) => `\u7F3A\u7684\u8865\u4E0A\uFF1A${addCmd}\uFF08\u6309\u4E0A\u9762\u7684\u5E73\u53F0\u62A5\u9519\u6539\u6B63\u540E\u518D\u8865\uFF09\u3002`,
|
|
354
|
+
AN3_MIS: "\u503C\u4E0D\u7B26\u7684\u6309\u8BFB\u56DE\u7684\u503C\u751F\u6548\uFF0C\u6539\u4EF7 / \u6539\u6298\u6263\u4E0D\u5728\u672C\u547D\u4EE4\u8303\u56F4\u3002",
|
|
355
|
+
AN4: (shop, id) => `\u52A0\u5546\u54C1\u5931\u8D25\uFF0C\u56DE\u8BFB\u4E5F\u5931\u8D25\u4E86\uFF0C\u67E5\u4E0D\u5230\u6D3B\u52A8 ${id} \u91CC\u672C\u6B21\u7684 SKU \u6709\u6CA1\u6709\u6302\u4E0A\u3002\u5148\u7528 \`tiktok promotions get --shop ${shop} --id ${id}\` \u6838\u5BF9\uFF0C\u518D\u51B3\u5B9A\u662F\u5426\u91CD\u8DD1\uFF08\u5DF2\u6302\u4E0A\u7684\u4F1A\u5728\u9884\u8BFB\u90A3\u6B65\u88AB\u8BC6\u522B\uFF0C\u91CD\u8DD1\u4E0D\u4F1A\u91CD\u590D\u52A0\uFF09\u3002`
|
|
356
|
+
};
|
|
325
357
|
var COMMANDS = [
|
|
326
358
|
{
|
|
327
359
|
name: "orders list",
|
|
@@ -953,20 +985,26 @@ var COMMANDS = [
|
|
|
953
985
|
},
|
|
954
986
|
{
|
|
955
987
|
name: "promotions create-discount",
|
|
956
|
-
summary: "\u5EFA\u5546\u54C1\u6298\u6263\u6D3B\u52A8 FIXED_PRICE\uFF08--title [--product] --price <skuId>:<\u4E00\u53E3\u4EF7>|<productId>/<skuId>:<\u4E00\u53E3\u4EF7>[,...] [--days 180]\uFF09\u3002\u4E24\u6B65:\u5EFA\u58F3+\u52A0\u54C1\uFF0C\u53EF\u591A\u5546\u54C1",
|
|
957
|
-
flags: ["days", "price", "product", "title"],
|
|
988
|
+
summary: "\u5EFA\u5546\u54C1\u6298\u6263\u6D3B\u52A8 FIXED_PRICE\uFF08--price \u4E00\u53E3\u4EF7\uFF09\u6216 DIRECT_DISCOUNT\uFF08--percent \u51CFN%\uFF09\uFF08--title [--product] --price <skuId>:<\u4E00\u53E3\u4EF7>|<productId>/<skuId>:<\u4E00\u53E3\u4EF7>[,...] \u6216 --percent <skuId>:<\u51CFN%>|<productId>/<skuId>:<\u51CFN%>[,...] [--days 180]\uFF09\u3002--percent 85 = \u51CF85%\u3001\u6309\u539F\u4EF715%\u5356\uFF08\u625385\u6298\u8981\u4F2015\uFF09\u3002\u4E24\u6B65:\u5EFA\u58F3+\u52A0\u54C1\uFF0C\u53EF\u591A\u5546\u54C1",
|
|
989
|
+
flags: ["days", "percent", "price", "product", "title"],
|
|
958
990
|
write: true,
|
|
959
991
|
validate: validateCreateDiscount,
|
|
960
992
|
preview: ({ args: args2 }) => {
|
|
961
993
|
const { begin, end } = discountWindow(args2);
|
|
962
994
|
return [
|
|
963
995
|
{ step: "1/2 \u5EFA\u6D3B\u52A8\u58F3", method: "POST", path: "/promotion/202309/activities", body: discountActivityBody(args2, begin, end) },
|
|
964
|
-
{ step: "2/2 \u52A0\u5546\u54C1+\u4E00\u53E3\u4EF7", method: "PUT", path: "/promotion/202309/activities/{activity_id}/products", body: discountProductsBody(args2), human: discountHuman(args2) }
|
|
996
|
+
{ step: discountValueFlag(args2) === "percent" ? "2/2 \u52A0\u5546\u54C1+\u51CFN%" : "2/2 \u52A0\u5546\u54C1+\u4E00\u53E3\u4EF7", method: "PUT", path: "/promotion/202309/activities/{activity_id}/products", body: discountProductsBody(args2), human: discountHuman(args2) }
|
|
965
997
|
];
|
|
966
998
|
},
|
|
967
999
|
run: async ({ shop, args: args2 }) => {
|
|
968
1000
|
const { begin, end } = discountWindow(args2);
|
|
969
1001
|
const submitted = submittedSkus(args2);
|
|
1002
|
+
const dd = discountValueFlag(args2) === "percent";
|
|
1003
|
+
const field = dd ? "discount" : "amount";
|
|
1004
|
+
const flag = discountValueFlag(args2);
|
|
1005
|
+
const rawVal = discountValueRaw(args2);
|
|
1006
|
+
const allItems = rawVal.split(",");
|
|
1007
|
+
const intent = { type: dd ? "DIRECT_DISCOUNT" : "FIXED_PRICE", flag, days: Number(args2.days ?? 180), addCmd: (aid) => addProductsCmd(shop, aid, args2.product, flag, allItems, true) };
|
|
970
1008
|
const created = await proxy("POST", shop, "/promotion/202309/activities", { body: discountActivityBody(args2, begin, end) });
|
|
971
1009
|
if (!created.ok) {
|
|
972
1010
|
const err = created.error;
|
|
@@ -974,7 +1012,7 @@ var COMMANDS = [
|
|
|
974
1012
|
case "maybe_landed":
|
|
975
1013
|
return { ...created, error: { ...err, message: `${err.message} ${DISCOUNT_TEXT.maybeLanded}` } };
|
|
976
1014
|
case "dup":
|
|
977
|
-
return { ...created, error: { ...err, message: `${err.message} ${await dupSelfCheck(shop, args2.title, submitted)}` } };
|
|
1015
|
+
return { ...created, error: { ...err, message: `${err.message} ${await dupSelfCheck(shop, args2.title, submitted, field, intent)}` } };
|
|
978
1016
|
case "rejected":
|
|
979
1017
|
return created;
|
|
980
1018
|
}
|
|
@@ -996,20 +1034,21 @@ var COMMANDS = [
|
|
|
996
1034
|
if (!withProducts.ok) {
|
|
997
1035
|
const { retry_after_s: _dropped, ...err } = withProducts.error;
|
|
998
1036
|
let note;
|
|
999
|
-
const c = rb.ok ? compareReadback(submitted, rb.data) : null;
|
|
1037
|
+
const c = rb.ok ? compareReadback(submitted, rb.data, field) : null;
|
|
1000
1038
|
if (!c) note = DISCOUNT_TEXT.addFailReadbackFailed(shop, activityId);
|
|
1001
1039
|
else {
|
|
1002
|
-
if (c.missing.length === 0 && c.mismatched.length === 0) note = DISCOUNT_TEXT.addFailAllAttached(submitted.length, activityId);
|
|
1003
|
-
else if (c.missing.length === submitted.length && c.productCount === 0) note = DISCOUNT_TEXT.addFailNoneAttached(shop, activityId);
|
|
1004
|
-
else note = DISCOUNT_TEXT.
|
|
1040
|
+
if (c.missing.length === 0 && c.mismatched.length === 0) note = DISCOUNT_TEXT.addFailAllAttached(submitted.length, activityId, dd);
|
|
1041
|
+
else if (c.missing.length === submitted.length && c.productCount === 0) note = DISCOUNT_TEXT.addFailNoneAttached(shop, activityId, addProductsCmd(shop, activityId, args2.product, flag, allItems, false));
|
|
1042
|
+
else if (c.missing.length === 0) note = DISCOUNT_TEXT.addFailPartialMismatch(problemsText(c, field), shop, activityId, dd);
|
|
1043
|
+
else note = DISCOUNT_TEXT.addFailPartial(problemsText(c, field), shop, activityId, addProductsCmd(shop, activityId, args2.product, flag, rawItemsFor(rawVal, c.missing), false), dd);
|
|
1005
1044
|
}
|
|
1006
1045
|
return { ok: false, error: { ...err, retryable: false }, data: { activity_id: activityId, readback, note }, meta: withProducts.meta };
|
|
1007
1046
|
}
|
|
1008
1047
|
const ours = [];
|
|
1009
|
-
const diff = rb.ok ? compareReadback(submitted, rb.data) : null;
|
|
1010
|
-
if (!diff) ours.push(DISCOUNT_TEXT.readbackFailed(activityId));
|
|
1048
|
+
const diff = rb.ok ? compareReadback(submitted, rb.data, field) : null;
|
|
1049
|
+
if (!diff) ours.push(DISCOUNT_TEXT.readbackFailed(shop, activityId));
|
|
1011
1050
|
else {
|
|
1012
|
-
const problems = problemsText(diff);
|
|
1051
|
+
const problems = problemsText(diff, field);
|
|
1013
1052
|
if (problems) ours.push(DISCOUNT_TEXT.readbackDiffers(activityId, problems));
|
|
1014
1053
|
}
|
|
1015
1054
|
const putData = withProducts.data ?? {};
|
|
@@ -1018,6 +1057,25 @@ var COMMANDS = [
|
|
|
1018
1057
|
return { ok: true, data, meta: withProducts.meta };
|
|
1019
1058
|
}
|
|
1020
1059
|
},
|
|
1060
|
+
{
|
|
1061
|
+
name: "promotions add-products",
|
|
1062
|
+
summary: ADD_TEXT.SUM_ADD,
|
|
1063
|
+
flags: ["id", "percent", "price", "product"],
|
|
1064
|
+
write: true,
|
|
1065
|
+
validate: validateAddProducts,
|
|
1066
|
+
// 🔴 命令块只字面读 args.id / args.product,值旗标经 discountValueFlag / discountValueRaw(它们字面读 args.percent / args.price);
|
|
1067
|
+
// ⛔ 不得提到 discountHuman / validateCreateDiscount / discountActivityBody / discountWindow(它们读 days / title,本命令没有)
|
|
1068
|
+
preview: ({ args: args2 }) => addProductsPlan(args2.id, discountValueFlag(args2), discountValueRaw(args2), args2.product),
|
|
1069
|
+
run: ({ shop, args: args2 }) => runAddProducts(shop, args2.id, discountValueFlag(args2), discountValueRaw(args2), args2.product)
|
|
1070
|
+
},
|
|
1071
|
+
{
|
|
1072
|
+
name: "promotions get",
|
|
1073
|
+
summary: ADD_TEXT.SUM_GET,
|
|
1074
|
+
flags: ["id"],
|
|
1075
|
+
listKey: "products",
|
|
1076
|
+
validate: validateGet,
|
|
1077
|
+
run: ({ shop, args: args2 }) => runGet(shop, args2.id)
|
|
1078
|
+
},
|
|
1021
1079
|
{
|
|
1022
1080
|
name: "promotions deactivate",
|
|
1023
1081
|
summary: "\u7EC8\u6B62/\u505C\u7528\u4FC3\u9500\u6D3B\u52A8\uFF08--id \u5FC5\u586B\uFF09\u3002\u4E0D\u53EF\u9006",
|
|
@@ -1466,27 +1524,41 @@ function findCommand(tokens) {
|
|
|
1466
1524
|
}
|
|
1467
1525
|
return null;
|
|
1468
1526
|
}
|
|
1469
|
-
var DISCOUNT_FLAGS = ["shop", "apply", "actor", "title", "product", "price", "days"];
|
|
1527
|
+
var DISCOUNT_FLAGS = ["shop", "apply", "actor", "title", "product", "price", "percent", "days"];
|
|
1528
|
+
function discountValueFlag(args2) {
|
|
1529
|
+
return "percent" in args2 ? "percent" : "price";
|
|
1530
|
+
}
|
|
1531
|
+
function discountValueRaw(args2) {
|
|
1532
|
+
return discountValueFlag(args2) === "percent" ? args2.percent ?? "" : args2.price ?? "";
|
|
1533
|
+
}
|
|
1470
1534
|
var PRICE_ITEM = /^(?:([^:,\s/]+)\/)?([^:,\s/]+):(0|[1-9]\d*)(?:\.(\d{1,2}))?$/;
|
|
1471
|
-
|
|
1535
|
+
var PCT_ITEM = /^(?:([^:,\s/]+)\/)?([^:,\s/]+):([1-9]\d?)$/;
|
|
1536
|
+
function parsePriceItems(raw, defaultProduct, flag = "price") {
|
|
1472
1537
|
const items = [];
|
|
1473
1538
|
const seen = /* @__PURE__ */ new Set();
|
|
1539
|
+
const unit = flag === "percent" ? "<\u51CFN%>" : "<\u4EF7>";
|
|
1474
1540
|
for (const part of raw.split(",")) {
|
|
1475
|
-
const m = PRICE_ITEM.exec(part);
|
|
1541
|
+
const m = (flag === "percent" ? PCT_ITEM : PRICE_ITEM).exec(part);
|
|
1476
1542
|
if (!m) {
|
|
1477
|
-
return { ok: false, message: `--price \u6BCF\u4E00\u9879\u5FC5\u987B\u662F <skuId>:<\u4E00\u53E3\u4EF7> \u6216 <productId>/<skuId>:<\u4E00\u53E3\u4EF7>\uFF08\u5341\u8FDB\u5236\u6570\u5B57\uFF0C\u6700\u591A\u4E24\u4F4D\u5C0F\u6570\u3001\u4E0D\u8981\u524D\u5BFC\u96F6\uFF0C\u5982 25.42\uFF09\uFF0C\u591A\u9879\u7528\u9017\u53F7\u8FDE\u63A5\u3001\u5404\u9879\u4E4B\u95F4\u4E0D\u8981\u6709\u7A7A\u683C\uFF0C\u5982 --price 173707:29.90,173708:32.00\uFF1B\u6536\u5230\u300C${part}\u300D` };
|
|
1543
|
+
return flag === "percent" ? { ok: false, message: `--percent \u6BCF\u4E00\u9879\u5FC5\u987B\u662F <skuId>:<N> \u6216 <productId>/<skuId>:<N>\uFF0CN \u662F 1\u201399 \u7684\u6574\u6570\uFF0C\u8868\u793A\u300C\u51CF N%\u300D\uFF0885 = \u51CF 85%\uFF0C\u6309\u539F\u4EF7 15% \u5356\uFF1B\u5E97\u4E3B\u8BF4\u300C\u6253 85 \u6298\u300D\u8981\u4F20 15\uFF09\uFF1B\u6536\u5230\u300C${part}\u300D` } : { ok: false, message: `--price \u6BCF\u4E00\u9879\u5FC5\u987B\u662F <skuId>:<\u4E00\u53E3\u4EF7> \u6216 <productId>/<skuId>:<\u4E00\u53E3\u4EF7>\uFF08\u5341\u8FDB\u5236\u6570\u5B57\uFF0C\u6700\u591A\u4E24\u4F4D\u5C0F\u6570\u3001\u4E0D\u8981\u524D\u5BFC\u96F6\uFF0C\u5982 25.42\uFF09\uFF0C\u591A\u9879\u7528\u9017\u53F7\u8FDE\u63A5\u3001\u5404\u9879\u4E4B\u95F4\u4E0D\u8981\u6709\u7A7A\u683C\uFF0C\u5982 --price 173707:29.90,173708:32.00\uFF1B\u6536\u5230\u300C${part}\u300D` };
|
|
1478
1544
|
}
|
|
1479
|
-
const [, explicitPid, sid
|
|
1545
|
+
const [, explicitPid, sid] = m;
|
|
1480
1546
|
if (explicitPid && defaultProduct && explicitPid !== defaultProduct) {
|
|
1481
|
-
return { ok: false, message:
|
|
1547
|
+
return { ok: false, message: `--${flag} \u7684\u300C${part}\u300D\u6307\u5B9A\u4E86\u5546\u54C1 ${explicitPid}\uFF0C\u4E0E --product ${defaultProduct} \u4E0D\u4E00\u81F4\uFF1B\u591A\u5546\u54C1\u8BF7\u628A --product \u53BB\u6389\u3001\u6BCF\u9879\u90FD\u5199\u6210 <productId>/<skuId>:${unit}` };
|
|
1482
1548
|
}
|
|
1483
1549
|
const pid = explicitPid ?? defaultProduct;
|
|
1484
1550
|
if (!pid) {
|
|
1485
|
-
return { ok: false, message:
|
|
1551
|
+
return { ok: false, message: `--${flag} \u7684\u300C${part}\u300D\u6CA1\u5E26 productId\uFF0C\u800C\u4F60\u4E5F\u6CA1\u4F20 --product\uFF1B\u8981\u4E48\u52A0 --product\uFF0C\u8981\u4E48\u5199\u6210 <productId>/<skuId>:${unit}` };
|
|
1552
|
+
}
|
|
1553
|
+
let amount;
|
|
1554
|
+
if (flag === "percent") {
|
|
1555
|
+
amount = m[3];
|
|
1556
|
+
} else {
|
|
1557
|
+
const [, , , intPart, frac] = m;
|
|
1558
|
+
amount = frac === void 0 ? intPart : `${intPart}.${frac}`;
|
|
1559
|
+
if (!(Number(amount) > 0)) return { ok: false, message: `--price \u7684\u4E00\u53E3\u4EF7\u5FC5\u987B\u5927\u4E8E 0\uFF1B\u6536\u5230\u300C${part}\u300D` };
|
|
1486
1560
|
}
|
|
1487
|
-
|
|
1488
|
-
if (!(Number(amount) > 0)) return { ok: false, message: `--price \u7684\u4E00\u53E3\u4EF7\u5FC5\u987B\u5927\u4E8E 0\uFF1B\u6536\u5230\u300C${part}\u300D` };
|
|
1489
|
-
if (seen.has(sid)) return { ok: false, message: `--price \u91CC\u540C\u4E00\u4E2A skuId \u91CD\u590D\u51FA\u73B0\uFF1A${sid}` };
|
|
1561
|
+
if (seen.has(sid)) return { ok: false, message: `--${flag} \u91CC\u540C\u4E00\u4E2A skuId \u91CD\u590D\u51FA\u73B0\uFF1A${sid}` };
|
|
1490
1562
|
seen.add(sid);
|
|
1491
1563
|
items.push({ pid, sid, amount });
|
|
1492
1564
|
}
|
|
@@ -1501,15 +1573,14 @@ function discountWindow(args2) {
|
|
|
1501
1573
|
function discountActivityBody(args2, begin, end) {
|
|
1502
1574
|
return {
|
|
1503
1575
|
title: args2.title,
|
|
1504
|
-
|
|
1576
|
+
// 🔴 由常量变条件 —— 正是 #9 的根因形态(字段写死);P1/P2 钉 DD、P9 钉 FP 逐字不变
|
|
1577
|
+
activity_type: discountValueFlag(args2) === "percent" ? "DIRECT_DISCOUNT" : "FIXED_PRICE",
|
|
1505
1578
|
product_level: "VARIATION",
|
|
1506
1579
|
begin_time: begin,
|
|
1507
1580
|
end_time: end
|
|
1508
1581
|
};
|
|
1509
1582
|
}
|
|
1510
|
-
function
|
|
1511
|
-
const parsed = parsePriceItems(args2.price ?? "", args2.product);
|
|
1512
|
-
const items = parsed.ok ? parsed.items : [];
|
|
1583
|
+
function productsBodyFromItems(items, flag, productLimits) {
|
|
1513
1584
|
const order = [];
|
|
1514
1585
|
const byPid = /* @__PURE__ */ new Map();
|
|
1515
1586
|
for (const it of items) {
|
|
@@ -1520,49 +1591,62 @@ function discountProductsBody(args2) {
|
|
|
1520
1591
|
byPid.get(it.pid).push({ sid: it.sid, amount: it.amount });
|
|
1521
1592
|
}
|
|
1522
1593
|
return {
|
|
1523
|
-
products: order.map((pid) =>
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
activity_price_amount: it.amount,
|
|
1530
|
-
// 🔴 写侧裸串;读回叫 activity_price.amount
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
}))
|
|
1534
|
-
}))
|
|
1594
|
+
products: order.map((pid) => {
|
|
1595
|
+
const [ql, qpu] = productLimits?.get(pid) ?? [-1, -1];
|
|
1596
|
+
return {
|
|
1597
|
+
id: pid,
|
|
1598
|
+
quantity_limit: ql,
|
|
1599
|
+
quantity_per_user: qpu,
|
|
1600
|
+
skus: byPid.get(pid).map((it) => flag === "percent" ? { id: it.sid, discount: it.amount, quantity_limit: -1, quantity_per_user: -1 } : { id: it.sid, activity_price_amount: it.amount, quantity_limit: -1, quantity_per_user: -1 })
|
|
1601
|
+
// 🔴 写侧裸串;读回叫 activity_price.amount
|
|
1602
|
+
};
|
|
1603
|
+
})
|
|
1535
1604
|
};
|
|
1536
1605
|
}
|
|
1606
|
+
function discountProductsBody(args2) {
|
|
1607
|
+
const flag = discountValueFlag(args2);
|
|
1608
|
+
const parsed = parsePriceItems(discountValueRaw(args2), args2.product, flag);
|
|
1609
|
+
return productsBodyFromItems(parsed.ok ? parsed.items : [], flag);
|
|
1610
|
+
}
|
|
1611
|
+
function discountItemsHuman(items, flag) {
|
|
1612
|
+
return items.map((it) => flag === "percent" ? `\u5546\u54C1 ${it.pid} \u7684 SKU ${it.sid} \u51CF ${it.amount}%\uFF08\u6309\u539F\u4EF7 ${100 - Number(it.amount)}% \u552E\u5356\uFF09` : `\u5546\u54C1 ${it.pid} \u7684 SKU ${it.sid} \u552E\u4EF7\u5B9A\u4E3A ${it.amount}`).join("\uFF1B");
|
|
1613
|
+
}
|
|
1537
1614
|
function discountHuman(args2) {
|
|
1538
|
-
const
|
|
1615
|
+
const flag = discountValueFlag(args2);
|
|
1616
|
+
const parsed = parsePriceItems(discountValueRaw(args2), args2.product, flag);
|
|
1539
1617
|
const days = Number(args2.days ?? 180);
|
|
1540
|
-
const list = parsed.ok ? parsed.items
|
|
1618
|
+
const list = parsed.ok ? discountItemsHuman(parsed.items, flag) : `\uFF08--${flag} \u89E3\u6790\u5931\u8D25\uFF09`;
|
|
1541
1619
|
return `${list}\u3002\u539F\u4EF7\u5C06\u663E\u793A\u4E3A\u5212\u7EBF\u4EF7\u3002\u6D3B\u52A8\u5171 ${days} \u5929\uFF0C\u4ECE 15 \u5206\u949F\u540E\u5F00\u59CB \u2014\u2014 \u521A\u5EFA\u5B8C\u53BB\u5546\u54C1\u9875\u770B\u4EF7\u683C\u6CA1\u53D8\u662F\u6B63\u5E38\u7684\uFF0C\u90A3\u65F6\u6D3B\u52A8\u8FD8\u662F NOT_START\u3002`;
|
|
1542
1620
|
}
|
|
1543
1621
|
function validateCreateDiscount(ctx2) {
|
|
1544
1622
|
const { args: args2, rest } = ctx2;
|
|
1545
1623
|
for (const k of Object.keys(args2)) {
|
|
1546
1624
|
if (DISCOUNT_FLAGS.includes(k)) continue;
|
|
1547
|
-
if (k === "percent") {
|
|
1548
|
-
return { ok: false, message: "\u672C\u7248\u4E0D\u652F\u6301\u767E\u5206\u6BD4\u6298\u6263\uFF08--percent\uFF09\u3002\u8BF7\u5148\u7528 tiktok products get --shop <id> --product <pid> \u53D6 SKU \u6302\u724C\u4EF7\uFF0C\u81EA\u884C\u6298\u7B97\uFF08\u4FDD\u7559\u4E24\u4F4D\u5C0F\u6570\uFF09\u540E\u8D70 --price <skuId>:<\u6298\u540E\u4EF7>" };
|
|
1549
|
-
}
|
|
1550
1625
|
if (k === "sku") {
|
|
1551
|
-
return { ok: false, message: "\u672C\u547D\u4EE4\u6CA1\u6709 --sku\uFF1AskuId \u5199\u5728 --price \u91CC\uFF0C\u5982 --price 173707:29.90\uFF08\u6CA1\u4F20 --product \u65F6\u6BCF\u9879\u90FD\u8981\u5E26 productId\uFF0C\u5982 --price 1737048/173707:29.90\uFF09" };
|
|
1626
|
+
return "percent" in args2 ? { ok: false, message: "\u672C\u547D\u4EE4\u6CA1\u6709 --sku\uFF1AskuId \u5199\u5728 --percent \u91CC\uFF0C\u5982 --percent 173707:15\uFF08\u6CA1\u4F20 --product \u65F6\u6BCF\u9879\u90FD\u8981\u5E26 productId\uFF0C\u5982 --percent 1737048/173707:15\uFF09" } : { ok: false, message: "\u672C\u547D\u4EE4\u6CA1\u6709 --sku\uFF1AskuId \u5199\u5728 --price \u91CC\uFF0C\u5982 --price 173707:29.90\uFF08\u6CA1\u4F20 --product \u65F6\u6BCF\u9879\u90FD\u8981\u5E26 productId\uFF0C\u5982 --price 1737048/173707:29.90\uFF09" };
|
|
1552
1627
|
}
|
|
1553
1628
|
const own = DISCOUNT_FLAGS.filter((f) => !GLOBAL_FLAGS.includes(f));
|
|
1554
1629
|
const hint = suggestFlag(k, own, args2[k], Date.now(), "promotions create-discount");
|
|
1555
1630
|
const tip = !hint ? "" : hint.startsWith("--") ? `\uFF08\u4F60\u662F\u60F3\u7528 ${hint} \u5417\uFF1F\uFF09` : `\uFF08${hint}\uFF09`;
|
|
1556
1631
|
return { ok: false, message: `\u4E0D\u652F\u6301\u7684\u53C2\u6570 --${k}${tip}\uFF1B\u672C\u547D\u4EE4\u53EA\u8BA4 ${DISCOUNT_FLAGS.map((f) => "--" + f).join(" ")}` };
|
|
1557
1632
|
}
|
|
1633
|
+
const v3flag = "price" in args2 ? "price" : discountValueFlag(args2);
|
|
1558
1634
|
if (rest && rest.length > 0) {
|
|
1559
|
-
return { ok: false, message: `\u591A\u4F59\u7684\u4F4D\u7F6E\u53C2\u6570\u300C${rest.join(" ")}\u300D\u2014\u2014\u6BCF\u4E2A\u53C2\u6570\u53EA\u80FD\u5E26\u4E00\u4E2A\u503C\u3002\u591A\u4E2A SKU \u8981\u7528\u9017\u53F7\u8FDE\u6210\u4E00\u4E2A
|
|
1635
|
+
return { ok: false, message: `\u591A\u4F59\u7684\u4F4D\u7F6E\u53C2\u6570\u300C${rest.join(" ")}\u300D\u2014\u2014\u6BCF\u4E2A\u53C2\u6570\u53EA\u80FD\u5E26\u4E00\u4E2A\u503C\u3002\u591A\u4E2A SKU \u8981\u7528\u9017\u53F7\u8FDE\u6210\u4E00\u4E2A --${v3flag}\uFF0C\u5982 --${v3flag} A:12,B:15\uFF08\u4E0D\u80FD\u7528\u7A7A\u683C\u5206\u9694\uFF09\uFF1B\u82E5\u662F\u6807\u9898\u7B49\u503C\u91CC\u542B\u7A7A\u683C\uFF0C\u7ED9\u6574\u4E2A\u503C\u52A0\u5F15\u53F7\uFF0C\u5982 --title "Momo Sale"` };
|
|
1560
1636
|
}
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
}
|
|
1637
|
+
if ("price" in args2 && "percent" in args2) {
|
|
1638
|
+
return { ok: false, message: "--price \u4E0E --percent \u53EA\u80FD\u4E8C\u9009\u4E00\uFF1A\u4E00\u53E3\u4EF7\u7528 --price\uFF0C\u767E\u5206\u6BD4\u6298\u6263\u7528 --percent\u3002" };
|
|
1639
|
+
}
|
|
1640
|
+
if (!("price" in args2) && !("percent" in args2)) {
|
|
1641
|
+
return { ok: false, message: `--price \u5FC5\u586B\uFF08\u767E\u5206\u6BD4\u6298\u6263\u6539\u7528 --percent\uFF0C\u4E24\u8005\u4E8C\u9009\u4E00\uFF09\uFF0C\u4E14\u5FC5\u987B\u5E26\u503C\uFF08\u53EA\u5199 --price \u4E0D\u7ED9\u503C\u4F1A\u88AB\u89E3\u6790\u6210\u5B57\u7B26\u4E32 "true"\uFF0C\u5199\u6210 --price= \u5219\u662F\u7A7A\u503C\uFF0C\u4E24\u79CD\u90FD\u4E0D\u7B97\uFF09` };
|
|
1642
|
+
}
|
|
1643
|
+
if (!args2.title || args2.title === "true" || !args2.title.trim()) {
|
|
1644
|
+
return { ok: false, message: `--title \u5FC5\u586B\uFF0C\u4E14\u5FC5\u987B\u5E26\u503C\uFF08\u53EA\u5199 --title \u4E0D\u7ED9\u503C\u4F1A\u88AB\u89E3\u6790\u6210\u5B57\u7B26\u4E32 "true"\uFF0C\u5199\u6210 --title= \u5219\u662F\u7A7A\u503C\uFF0C\u4E24\u79CD\u90FD\u4E0D\u7B97\uFF09` };
|
|
1645
|
+
}
|
|
1646
|
+
const flag = discountValueFlag(args2);
|
|
1647
|
+
const val = flag === "percent" ? args2.percent : args2.price;
|
|
1648
|
+
if (!val || val === "true" || !val.trim()) {
|
|
1649
|
+
return { ok: false, message: `--${flag} \u5FC5\u586B\uFF0C\u4E14\u5FC5\u987B\u5E26\u503C\uFF08\u53EA\u5199 --${flag} \u4E0D\u7ED9\u503C\u4F1A\u88AB\u89E3\u6790\u6210\u5B57\u7B26\u4E32 "true"\uFF0C\u5199\u6210 --${flag}= \u5219\u662F\u7A7A\u503C\uFF0C\u4E24\u79CD\u90FD\u4E0D\u7B97\uFF09` };
|
|
1566
1650
|
}
|
|
1567
1651
|
if (args2.title !== args2.title.trim()) {
|
|
1568
1652
|
return { ok: false, message: `--title \u9996\u5C3E\u4E0D\u80FD\u6709\u7A7A\u767D\uFF08\u6536\u5230\u300C${args2.title}\u300D\uFF09\uFF1A\u649E\u91CD\u540D\u65F6 CLI \u6309\u6807\u9898\u4E25\u683C\u76F8\u7B49\u67E5\u540C\u540D\u6D3B\u52A8\uFF0C\u5E73\u53F0\u82E5\u53BB\u6389\u9996\u5C3E\u7A7A\u767D\u5C31\u4F1A\u5BF9\u4E0D\u4E0A\u3002\u8BF7\u53BB\u6389\u9996\u5C3E\u7A7A\u767D\u540E\u91CD\u8DD1` };
|
|
@@ -1571,9 +1655,9 @@ function validateCreateDiscount(ctx2) {
|
|
|
1571
1655
|
return { ok: false, message: `--product \u5FC5\u586B\uFF0C\u4E14\u5FC5\u987B\u5E26\u503C\uFF08\u53EA\u5199 --product \u4E0D\u7ED9\u503C\u4F1A\u88AB\u89E3\u6790\u6210\u5B57\u7B26\u4E32 "true"\uFF0C\u5199\u6210 --product= \u5219\u662F\u7A7A\u503C\uFF0C\u4E24\u79CD\u90FD\u4E0D\u7B97\uFF09` };
|
|
1572
1656
|
}
|
|
1573
1657
|
if (args2.product?.includes(",")) {
|
|
1574
|
-
return { ok: false, message:
|
|
1658
|
+
return { ok: false, message: `--product \u53EA\u6536\u4E00\u4E2A\u5546\u54C1 id\uFF1B\u591A\u5546\u54C1\u8BF7\u5728 --${flag} \u91CC\u5199 <productId>/<skuId>:${flag === "percent" ? "<\u51CFN%>" : "<\u4EF7>"}` };
|
|
1575
1659
|
}
|
|
1576
|
-
const parsed = parsePriceItems(
|
|
1660
|
+
const parsed = parsePriceItems(val, args2.product, flag);
|
|
1577
1661
|
if (!parsed.ok) return parsed;
|
|
1578
1662
|
if ("days" in args2) {
|
|
1579
1663
|
const raw = args2.days;
|
|
@@ -1592,18 +1676,21 @@ var DISCOUNT_TEXT = {
|
|
|
1592
1676
|
noCreateId: (title) => `\u5EFA\u58F3\u8FD4\u56DE\u6210\u529F\u4F46\u6CA1\u62FF\u5230 activity_id \u2014\u2014 \u26A0\uFE0F \u5E73\u53F0\u4E0A\u5F88\u53EF\u80FD\u5DF2\u7ECF\u6709\u8FD9\u6761\u58F3\u4E86\uFF08\u6807\u9898\u300C${title}\u300D\uFF09\u3002\u522B\u6362\u6807\u9898\uFF0C\u76F4\u63A5\u7528\u539F\u6807\u9898\u91CD\u8DD1\u539F\u547D\u4EE4\uFF1A\u91CD\u8DD1\u4F1A\u649E\u91CD\u540D\uFF0C\u90A3\u6761\u63D0\u793A\u4F1A\u544A\u8BC9\u4F60\u4E0B\u4E00\u6B65\u3002`,
|
|
1593
1677
|
// ⑦ 撞重名后自查的六种结论(前面由调用方拼上平台原文 + 一个半角空格)
|
|
1594
1678
|
dupSame: (title, aid, status) => `\u26A0\uFE0F \u540C\u540D\u6D3B\u52A8\u300C${title}\u300D\u5DF2\u5B58\u5728\uFF08\u6D3B\u52A8 ${aid}\uFF0C${status}\uFF09\uFF0C\u6302\u7684\u5546\u54C1\u4E0E\u672C\u6B21\u63D0\u4EA4\u5B8C\u5168\u4E00\u81F4\u2014\u2014\u8FD9\u5C31\u662F\u4F60\u8981\u7684\u6D3B\u52A8\uFF0C\u5DF2\u7ECF\u5EFA\u597D\u4E86\uFF1A\u522B\u91CD\u5EFA\u3002`,
|
|
1595
|
-
dupEmpty: (title, aid, status,
|
|
1679
|
+
dupEmpty: (title, aid, status, addCmd) => `\u26A0\uFE0F \u540C\u540D\u6D3B\u52A8\u300C${title}\u300D\u5DF2\u5B58\u5728\uFF08\u6D3B\u52A8 ${aid}\uFF0C${status}\uFF09\uFF0C\u4F46\u5B83\u662F\u4E00\u6761\u7A7A\u58F3\uFF08\u6CA1\u6709\u4EFB\u4F55\u5546\u54C1\uFF09\u2014\u2014\u76F4\u63A5\u628A\u5546\u54C1\u6302\u4E0A\u53BB\uFF1A${addCmd}\uFF1B\u522B\u91CD\u5EFA\u3002`,
|
|
1680
|
+
// v7 D4 / #36:否定分支 —— ⛔ 不指名具体哪一项(status 那格类型时长可能都对,写「类型或时长不符」是假原因);措辞由 create-discount 线二轮拍板
|
|
1681
|
+
dupEmptyOther: (title, aid, status, shop) => `\u26A0\uFE0F \u540C\u540D\u6D3B\u52A8\u300C${title}\u300D\u5DF2\u5B58\u5728\uFF08\u6D3B\u52A8 ${aid}\uFF0C${status}\uFF09\uFF0C\u5B83\u662F\u4E00\u6761\u7A7A\u58F3\uFF0C\u4F46\u4E0D\u662F\u4F60\u8FD9\u6B21\u8981\u5EFA\u7684\u90A3\u6761\uFF08\u7C7B\u578B\u3001\u65F6\u957F\u6216\u72B6\u6001\u6709\u51FA\u5165\uFF09\u2014\u2014\u522B\u5F80\u5B83\u91CC\u9762\u52A0\u54C1\uFF08\u6302\u8FDB\u53BB\u7684\u5546\u54C1\u4F1A\u8DDF\u7740\u5B83\u7684\u7C7B\u578B\u3001\u65F6\u957F\u548C\u751F\u6548\u72B6\u6001\u8D70\uFF0C\u4E0D\u662F\u4F60\u8FD9\u6B21\u8981\u7684\uFF09\uFF0C\u4E5F\u522B\u5148\u6E05\u7406\u518D\u7528\u539F\u6807\u9898\u91CD\u8DD1\uFF08\u6E05\u7406\u4E0D\u4F1A\u91CA\u653E\u6807\u9898\uFF09\uFF1A\u6362\u4E00\u4E2A\u6807\u9898\u91CD\u8DD1\u539F\u547D\u4EE4\uFF1B\u4E0D\u8981\u8FD9\u6761\u58F3\u4E86\u518D\u6E05\u7406\uFF1A${deactivateCmd(shop, aid)}\u3002`,
|
|
1596
1682
|
dupOwner: (title, aid, status, problems) => `\u26A0\uFE0F \u540C\u540D\u6D3B\u52A8\u300C${title}\u300D\u5DF2\u5B58\u5728\uFF08\u6D3B\u52A8 ${aid}\uFF0C${status}\uFF09\uFF0C\u6302\u7684\u5546\u54C1\u4E0E\u672C\u6B21\u63D0\u4EA4\u4E0D\u4E00\u81F4\uFF1A${problems}\u2014\u2014\u522B\u52A8\u5B83\uFF0C\u4E5F\u5148\u522B\u91CD\u5EFA\uFF1A\u628A\u5B83\u544A\u8BC9\u5E97\u4E3B\uFF0C\u95EE\u662F\u5C31\u7528\u8FD9\u6761\uFF0C\u8FD8\u662F\u6362\u4E2A\u6807\u9898\u53E6\u5EFA\u3002`,
|
|
1597
1683
|
dupRetitle: (title) => `\u26A0\uFE0F \u672A\u5F00\u59CB / \u8FDB\u884C\u4E2D\u7684\u6D3B\u52A8\u91CC\u6CA1\u6709\u300C${title}\u300D\u2014\u2014\u8FD9\u4E2A\u6807\u9898\u88AB\u4E00\u6761\u5DF2\u7EC8\u6B62\u6216\u5DF2\u8FC7\u671F\u7684\u6D3B\u52A8\u5360\u7740\uFF0C\u6362\u4E2A\u6807\u9898\u91CD\u8DD1\u539F\u547D\u4EE4\u3002`,
|
|
1598
1684
|
dupUnclear: (title, queryError) => `\u26A0\uFE0F \u540C\u540D\u6D3B\u52A8\u300C${title}\u300D\u5DF2\u5B58\u5728\uFF0C\u4F46\u6CA1\u80FD\u67E5\u6E05\u5B83\u7684\u72B6\u6001\uFF08${queryError}\uFF09\u2014\u2014\u522B\u6362\u6807\u9898\u3001\u522B\u91CD\u5EFA\uFF0C\u7A0D\u540E\u7528\u539F\u6807\u9898\u91CD\u8DD1\u539F\u547D\u4EE4\u518D\u770B\uFF1B\u8FDE\u7EED\u4E24\u6B21\u90FD\u662F\u8FD9\u53E5\uFF0C\u5C31\u5982\u5B9E\u544A\u8BC9\u5E97\u4E3B\u300C\u6D3B\u52A8\u53EF\u80FD\u5DF2\u5EFA\uFF0C\u4F46\u67E5\u4E0D\u6E05\u300D\u3002`,
|
|
1599
1685
|
dupMulti: (title, found) => `\u26A0\uFE0F \u672A\u5F00\u59CB / \u8FDB\u884C\u4E2D\u7684\u6D3B\u52A8\u91CC\u6709 ${found.length} \u6761\u53EB\u300C${title}\u300D\uFF08${found.map((a) => `${a.id}\uFF1A${a.status}`).join("\uFF1B")}\uFF09\u2014\u2014\u522B\u52A8\u5B83\u4EEC\uFF0C\u4E5F\u5148\u522B\u91CD\u5EFA\uFF1A\u628A\u5B83\u4EEC\u544A\u8BC9\u5E97\u4E3B\uFF0C\u95EE\u600E\u4E48\u5904\u7406\u3002`,
|
|
1600
1686
|
// ⑧ 加品失败后按回读下结论
|
|
1601
|
-
addFailAllAttached: (n, id) => `\u52A0\u5546\u54C1\u62A5\u4E86\u9519\uFF0C\u4F46\u56DE\u8BFB\u663E\u793A\u63D0\u4EA4\u7684 ${n} \u4E2A SKU \u90FD\u5DF2\u6309\u4EF7\u6302\u4E0A\uFF08\u6D3B\u52A8 ${id} \u7EA6 15 \u5206\u949F\u540E\u5F00\u59CB\uFF09\u2014\u2014\u522B\u6E05\u7406\uFF0C\u4E5F\u522B\u91CD\u8DD1\u672C\u547D\u4EE4\u3002`,
|
|
1602
|
-
addFailNoneAttached: (shop, id) => `\u52A0\u5546\u54C1\u5931\u8D25\uFF0C\u56DE\u8BFB\u663E\u793A\u6CA1\u6709\u4EFB\u4F55\u5546\u54C1\u6302\u4E0A\u2014\u2014\u6D3B\u52A8 ${id} \u662F\u4E00\u6761\u7A7A\u58F3\u3002\
|
|
1603
|
-
addFailPartial: (problems, shop, id) => `\u52A0\u5546\u54C1\u62A5\u4E86\u9519\uFF0C\u56DE\u8BFB\u663E\u793A\u6CA1\u6709\u5168\u90E8\u6302\u4E0A\uFF1A${problems}\u3002\
|
|
1604
|
-
|
|
1687
|
+
addFailAllAttached: (n, id, dd = false) => `\u52A0\u5546\u54C1\u62A5\u4E86\u9519\uFF0C\u4F46\u56DE\u8BFB\u663E\u793A\u63D0\u4EA4\u7684 ${n} \u4E2A SKU \u90FD\u5DF2\u6309${dd ? "\u6298\u6263" : "\u4EF7"}\u6302\u4E0A\uFF08\u6D3B\u52A8 ${id} \u7EA6 15 \u5206\u949F\u540E\u5F00\u59CB\uFF09\u2014\u2014\u522B\u6E05\u7406\uFF0C\u4E5F\u522B\u91CD\u8DD1\u672C\u547D\u4EE4\u3002`,
|
|
1688
|
+
addFailNoneAttached: (shop, id, addCmd) => `\u52A0\u5546\u54C1\u5931\u8D25\uFF0C\u56DE\u8BFB\u663E\u793A\u6CA1\u6709\u4EFB\u4F55\u5546\u54C1\u6302\u4E0A\u2014\u2014\u6D3B\u52A8 ${id} \u662F\u4E00\u6761\u7A7A\u58F3\u3002\u522B\u91CD\u8DD1\u672C\u547D\u4EE4\uFF08\u4F1A\u649E\u91CD\u540D\u6216\u518D\u5EFA\u4E00\u4E2A\u58F3\uFF09\uFF1A\u6309\u4E0A\u9762\u7684\u5E73\u53F0\u62A5\u9519\u6539\u6B63\u53C2\u6570\u540E\uFF0C\u7528 ${addCmd} \u628A\u5546\u54C1\u6302\u5230\u8FD9\u6761\u6D3B\u52A8\u4E0A\uFF08\u53EA\u6709\u9650\u6D41\u3001\u7F51\u7EDC\u7C7B\u62A5\u9519\u624D\u539F\u6837\u91CD\u8BD5\uFF09\uFF1B\u4E0D\u6253\u7B97\u7528\u8FD9\u6761\u6D3B\u52A8\u4E86\u518D\u6E05\u7406\uFF1A${deactivateCmd(shop, id)}\u3002`,
|
|
1689
|
+
addFailPartial: (problems, shop, id, addCmd, dd = false) => `\u52A0\u5546\u54C1\u62A5\u4E86\u9519\uFF0C\u56DE\u8BFB\u663E\u793A\u6CA1\u6709\u5168\u90E8\u6302\u4E0A\uFF1A${problems}\u3002\u8BF7\u5E97\u4E3B\u4E09\u9009\u4E00\uFF1A\u8865\u6302\u7F3A\u7684 SKU\uFF1A${addCmd}\uFF08\u6309\u4E0A\u9762\u7684\u5E73\u53F0\u62A5\u9519\u6539\u6B63\u540E\u518D\u8865\uFF09\uFF1B\u4FDD\u7559\u6D3B\u52A8 ${id}\uFF08\u7F3A\u7684 SKU \u4E0D\u6253\u6298\uFF0C${dd ? "\u6298\u6263\u4E0D\u7B26\u7684\u6309\u8BFB\u56DE\u7684\u6298\u6263\u751F\u6548" : "\u4EF7\u683C\u4E0D\u7B26\u7684\u6309\u8BFB\u56DE\u7684\u4EF7\u683C\u751F\u6548"}\uFF09\uFF1B\u6216\u6E05\u7406\u540E\u6574\u6761\u91CD\u5EFA\uFF1A${deactivateCmd(shop, id)}\uFF0C\u6E05\u7406\u540E\u6309\u4E0A\u9762\u7684\u5E73\u53F0\u62A5\u9519\u6539\u6B63\u53C2\u6570\u3001\u6362\u4E00\u4E2A\u6807\u9898\u91CD\u8DD1\u539F\u547D\u4EE4\uFF08\u26A0\uFE0F deactivate \u4E0D\u91CA\u653E\u6807\u9898\uFF0C\u7528\u539F\u6807\u9898\u91CD\u8DD1\u5FC5\u649E\u91CD\u540D\uFF09\u3002\u522B\u76F4\u63A5\u91CD\u8DD1\u672C\u547D\u4EE4\u3002`,
|
|
1690
|
+
addFailPartialMismatch: (problems, shop, id, dd = false) => `\u52A0\u5546\u54C1\u62A5\u4E86\u9519\uFF0C\u56DE\u8BFB\u663E\u793A\u5546\u54C1\u90FD\u6302\u4E0A\u4E86\uFF0C\u4F46\u503C\u4E0E\u63D0\u4EA4\u4E0D\u4E00\u81F4\uFF1A${problems}\u3002\u8BF7\u5E97\u4E3B\u4E8C\u9009\u4E00\uFF1A\u4FDD\u7559\u6D3B\u52A8 ${id}\uFF08${dd ? "\u6298\u6263\u4E0D\u7B26\u7684\u6309\u8BFB\u56DE\u7684\u6298\u6263\u751F\u6548" : "\u4EF7\u683C\u4E0D\u7B26\u7684\u6309\u8BFB\u56DE\u7684\u4EF7\u683C\u751F\u6548"}\uFF09\uFF0C\u6216\u6E05\u7406\u540E\u6574\u6761\u91CD\u5EFA\uFF1A${deactivateCmd(shop, id)}\uFF0C\u6E05\u7406\u540E\u6309\u4E0A\u9762\u7684\u5E73\u53F0\u62A5\u9519\u6539\u6B63\u53C2\u6570\u3001\u6362\u4E00\u4E2A\u6807\u9898\u91CD\u8DD1\u539F\u547D\u4EE4\uFF08\u26A0\uFE0F deactivate \u4E0D\u91CA\u653E\u6807\u9898\uFF0C\u7528\u539F\u6807\u9898\u91CD\u8DD1\u5FC5\u649E\u91CD\u540D\uFF09\u3002\u522B\u76F4\u63A5\u91CD\u8DD1\u672C\u547D\u4EE4\u3002`,
|
|
1691
|
+
addFailReadbackFailed: (shop, id) => `\u52A0\u5546\u54C1\u5931\u8D25\uFF0C\u56DE\u8BFB\u4E5F\u5931\u8D25\u4E86\uFF0C\u67E5\u4E0D\u5230\u6D3B\u52A8 ${id} \u91CC\u5546\u54C1\u6709\u6CA1\u6709\u6302\u4E0A\u3002\u522B\u91CD\u8DD1\u672C\u547D\u4EE4\uFF08\u4F1A\u518D\u5EFA\u4E00\u4E2A\u58F3\uFF09\uFF0C\u4E5F\u5148\u522B\u6E05\u7406\uFF1A\u5148\u7528 \`tiktok promotions get --shop ${shop} --id ${id}\` \u6838\u5BF9\uFF1B\u4ECD\u67E5\u4E0D\u6E05\u5C31\u5982\u5B9E\u544A\u8BC9\u5E97\u4E3B\u300C\u6D3B\u52A8\u5DF2\u5EFA\uFF0C\u5546\u54C1\u662F\u5426\u6302\u4E0A\u672A\u80FD\u786E\u8BA4\u300D\uFF1B\u786E\u8BA4\u6CA1\u6302\u4E0A\u518D\u6E05\u7406\uFF1A${deactivateCmd(shop, id)}\u3002`,
|
|
1605
1692
|
// ⑨ 成功路径的 warnings
|
|
1606
|
-
readbackFailed: (id) => `\u6D3B\u52A8 ${id} \u5DF2\u5EFA\u6210\u3001\u5546\u54C1\u5DF2\u63D0\u4EA4\uFF0C\u4F46\u56DE\u8BFB\u5931\u8D25\uFF0C\u672A\u80FD\u9A8C\u8BC1\u5546\u54C1\u662F\u5426\u6302\u4E0A\u2014\u2014\u4E0D\u8981\u91CD\u5EFA\u6D3B\u52A8\uFF1B\u5982\u5B9E\u544A\u8BC9\u5E97\u4E3B\u300C\u5DF2\u5EFA\uFF0C\u5546\u54C1\u662F\u5426\u6302\u4E0A\u672A\u80FD\u786E\u8BA4\u300D\u3002`,
|
|
1693
|
+
readbackFailed: (shop, id) => `\u6D3B\u52A8 ${id} \u5DF2\u5EFA\u6210\u3001\u5546\u54C1\u5DF2\u63D0\u4EA4\uFF0C\u4F46\u56DE\u8BFB\u5931\u8D25\uFF0C\u672A\u80FD\u9A8C\u8BC1\u5546\u54C1\u662F\u5426\u6302\u4E0A\u2014\u2014\u4E0D\u8981\u91CD\u5EFA\u6D3B\u52A8\uFF1B\u5148\u7528 \`tiktok promotions get --shop ${shop} --id ${id}\` \u6838\u5BF9\uFF0C\u4ECD\u67E5\u4E0D\u6E05\u518D\u5982\u5B9E\u544A\u8BC9\u5E97\u4E3B\u300C\u5DF2\u5EFA\uFF0C\u5546\u54C1\u662F\u5426\u6302\u4E0A\u672A\u80FD\u786E\u8BA4\u300D\u3002`,
|
|
1607
1694
|
readbackDiffers: (id, problems) => `\u6D3B\u52A8 ${id} \u5DF2\u5EFA\u6210\uFF0C\u4F46\u56DE\u8BFB\u4E0E\u63D0\u4EA4\u4E0D\u4E00\u81F4\uFF1A${problems}\u2014\u2014\u4E0D\u8981\u91CD\u5EFA\u6D3B\u52A8\uFF1B\u5982\u5B9E\u544A\u8BC9\u5E97\u4E3B\u54EA\u4E9B SKU \u672A\u786E\u8BA4\u6302\u4E0A\u3002`
|
|
1608
1695
|
};
|
|
1609
1696
|
var OBSERVED_REJECT_CODES = /* @__PURE__ */ new Set([
|
|
@@ -1637,9 +1724,10 @@ function createFailureVerdict(env2) {
|
|
|
1637
1724
|
return "maybe_landed";
|
|
1638
1725
|
}
|
|
1639
1726
|
function submittedSkus(args2) {
|
|
1640
|
-
|
|
1727
|
+
const dd = discountValueFlag(args2) === "percent";
|
|
1728
|
+
return discountProductsBody(args2).products.flatMap((p) => p.skus.map((s) => ({ sid: s.id, amount: dd ? s.discount : s.activity_price_amount })));
|
|
1641
1729
|
}
|
|
1642
|
-
function compareReadback(submitted, readback) {
|
|
1730
|
+
function compareReadback(submitted, readback, field = "amount") {
|
|
1643
1731
|
const products = readback?.products;
|
|
1644
1732
|
if (!Array.isArray(products)) return null;
|
|
1645
1733
|
const skus = products.flatMap((p) => Array.isArray(p?.skus) ? p.skus : []);
|
|
@@ -1658,17 +1746,19 @@ function compareReadback(submitted, readback) {
|
|
|
1658
1746
|
diff.missing.push(sid);
|
|
1659
1747
|
continue;
|
|
1660
1748
|
}
|
|
1661
|
-
const raw = hit.activity_price?.amount;
|
|
1749
|
+
const raw = field === "discount" ? hit.discount : hit.activity_price?.amount;
|
|
1662
1750
|
const got = raw === void 0 || raw === null || raw === "" ? void 0 : String(raw);
|
|
1663
1751
|
if (got === void 0 || Number(got) !== Number(amount)) diff.mismatched.push({ sid, submitted: amount, readback: got });
|
|
1664
1752
|
}
|
|
1665
1753
|
return diff;
|
|
1666
1754
|
}
|
|
1667
|
-
function problemsText(d) {
|
|
1755
|
+
function problemsText(d, field = "amount") {
|
|
1668
1756
|
const parts = [];
|
|
1669
1757
|
if (d.missing.length) parts.push(`\u7F3A ${d.missing.join("\u3001")}`);
|
|
1670
1758
|
if (d.mismatched.length) {
|
|
1671
|
-
|
|
1759
|
+
const label = field === "discount" ? "\u6298\u6263\u4E0D\u7B26" : "\u91D1\u989D\u4E0D\u7B26";
|
|
1760
|
+
const none = field === "discount" ? "\u65E0\u6298\u6263" : "\u65E0\u91D1\u989D";
|
|
1761
|
+
parts.push(`${label} ${d.mismatched.map((m) => `${m.sid}\uFF08\u63D0\u4EA4 ${m.submitted}\uFF0C\u8BFB\u56DE ${m.readback ?? none}\uFF09`).join("\u3001")}`);
|
|
1672
1762
|
}
|
|
1673
1763
|
return parts.join("\uFF1B");
|
|
1674
1764
|
}
|
|
@@ -1678,7 +1768,7 @@ function mergeWarnings(existing, ours) {
|
|
|
1678
1768
|
return [existing, ...ours];
|
|
1679
1769
|
}
|
|
1680
1770
|
var DUP_SEARCH_MAX_PAGES = 10;
|
|
1681
|
-
async function dupSelfCheck(shop, title, submitted) {
|
|
1771
|
+
async function dupSelfCheck(shop, title, submitted, field, intent) {
|
|
1682
1772
|
const found = /* @__PURE__ */ new Map();
|
|
1683
1773
|
for (const status of ["NOT_START", "ONGOING"]) {
|
|
1684
1774
|
let token;
|
|
@@ -1701,13 +1791,220 @@ async function dupSelfCheck(shop, title, submitted) {
|
|
|
1701
1791
|
const [hit] = found.values();
|
|
1702
1792
|
const g = await proxy("GET", shop, `/promotion/202309/activities/${hit.id}`, {});
|
|
1703
1793
|
if (!g.ok) return DISCOUNT_TEXT.dupUnclear(title, g.error.message);
|
|
1704
|
-
const d = compareReadback(submitted, g.data);
|
|
1794
|
+
const d = compareReadback(submitted, g.data, field);
|
|
1705
1795
|
if (!d) return DISCOUNT_TEXT.dupUnclear(title, "\u56DE\u8BFB\u7F3A products \u5B57\u6BB5");
|
|
1796
|
+
const gd = g.data;
|
|
1797
|
+
const shellType = gd?.activity_type;
|
|
1798
|
+
const typeNote = (shellType === "FIXED_PRICE" || shellType === "DIRECT_DISCOUNT") && shellType !== intent.type ? `\u7C7B\u578B\u4E0D\u7B26\uFF1A\u540C\u540D\u6D3B\u52A8\u662F ${shellType}\uFF0C\u672C\u6B21 --${intent.flag} \u5BF9\u5E94 ${intent.type}\uFF08\u4E0B\u9762\u7684\u4E0D\u4E00\u81F4\u662F\u7C7B\u578B\u5DEE\u5F02\u3001\u4E0D\u662F\u503C\u5DEE\u5F02\uFF09\uFF1B` : "";
|
|
1706
1799
|
if (d.missing.length === 0 && d.mismatched.length === 0 && d.total === submitted.length) {
|
|
1707
1800
|
return DISCOUNT_TEXT.dupSame(title, hit.id, hit.status);
|
|
1708
1801
|
}
|
|
1709
|
-
if (d.productCount === 0)
|
|
1710
|
-
|
|
1802
|
+
if (d.productCount === 0) {
|
|
1803
|
+
const fits = gd?.activity_type === intent.type && Number(gd?.end_time) - Number(gd?.begin_time) === intent.days * 86400 && gd?.status === "NOT_START";
|
|
1804
|
+
const echoStatus = String(gd?.status ?? hit.status);
|
|
1805
|
+
return fits ? DISCOUNT_TEXT.dupEmpty(title, hit.id, echoStatus, intent.addCmd(hit.id)) : DISCOUNT_TEXT.dupEmptyOther(title, hit.id, echoStatus, shop);
|
|
1806
|
+
}
|
|
1807
|
+
return DISCOUNT_TEXT.dupOwner(title, hit.id, hit.status, typeNote + (problemsText(d, field) || `\u591A\u51FA ${d.extra.join("\u3001")}`));
|
|
1808
|
+
}
|
|
1809
|
+
var GET_FLAGS = ["shop", "actor", "id"];
|
|
1810
|
+
function validateGet(ctx2) {
|
|
1811
|
+
const { args: args2, rest } = ctx2;
|
|
1812
|
+
for (const k of Object.keys(args2)) {
|
|
1813
|
+
if (k === "activity-id") return { ok: false, message: ADD_TEXT.AV2 };
|
|
1814
|
+
}
|
|
1815
|
+
for (const k of Object.keys(args2)) {
|
|
1816
|
+
if (GET_FLAGS.includes(k) || k === "help") continue;
|
|
1817
|
+
if (k === "apply") return { ok: false, message: "\u672C\u547D\u4EE4\u662F\u53EA\u8BFB\u547D\u4EE4\uFF0C\u6CA1\u6709 --apply\uFF08\u4E0D\u52A0 --apply \u4E5F\u4F1A\u76F4\u63A5\u8BFB\uFF09\uFF1B\u53BB\u6389\u5B83\u5373\u53EF" };
|
|
1818
|
+
const hint = suggestFlag(k, ["id"], args2[k], Date.now(), "promotions get");
|
|
1819
|
+
const tip = !hint ? "" : hint.startsWith("--") ? `\uFF08\u4F60\u662F\u60F3\u7528 ${hint} \u5417\uFF1F\uFF09` : `\uFF08${hint}\uFF09`;
|
|
1820
|
+
return { ok: false, message: `\u4E0D\u652F\u6301\u7684\u53C2\u6570 --${k}${tip}\uFF1B\u672C\u547D\u4EE4\u53EA\u8BA4 ${GET_FLAGS.map((f) => "--" + f).join(" ")}` };
|
|
1821
|
+
}
|
|
1822
|
+
if (rest && rest.length > 0) return { ok: false, message: ADD_TEXT.GV3(rest.join(" ")) };
|
|
1823
|
+
if (!args2.id || args2.id === "true" || !args2.id.trim()) {
|
|
1824
|
+
return { ok: false, message: `--id \u5FC5\u586B\uFF0C\u4E14\u5FC5\u987B\u5E26\u503C\uFF08\u6D3B\u52A8 id\uFF0C\u7EAF\u6570\u5B57\uFF0C\u5982 --id 7686081985965900001\uFF09` };
|
|
1825
|
+
}
|
|
1826
|
+
if (!/^\d+$/.test(args2.id)) return { ok: false, message: `--id \u5FC5\u987B\u662F\u7EAF\u6570\u5B57\u7684\u6D3B\u52A8 id\uFF08\u6536\u5230\u300C${args2.id}\u300D\uFF09` };
|
|
1827
|
+
return { ok: true };
|
|
1828
|
+
}
|
|
1829
|
+
async function runGet(shop, id) {
|
|
1830
|
+
return proxy("GET", shop, `/promotion/202309/activities/${id}`, {});
|
|
1831
|
+
}
|
|
1832
|
+
var ADD_PRODUCTS_FLAGS = ["shop", "apply", "actor", "id", "product", "price", "percent"];
|
|
1833
|
+
var ADD_ALLOWED_STATUS = ["NOT_START", "ONGOING"];
|
|
1834
|
+
var addProductsCmd = (shop, aid, product, flag, items, apply) => `\`tiktok promotions add-products --shop ${shop} --id ${aid}${product ? ` --product ${product}` : ""} --${flag} ${items.join(",")}${apply ? " --apply" : ""}\``;
|
|
1835
|
+
function rawItemsFor(raw, sids) {
|
|
1836
|
+
const want = new Set(sids);
|
|
1837
|
+
return raw.split(",").filter((part) => want.has(part.split(":")[0].split("/").pop() ?? ""));
|
|
1838
|
+
}
|
|
1839
|
+
function existingSkuValues(data, field) {
|
|
1840
|
+
const out2 = /* @__PURE__ */ new Map();
|
|
1841
|
+
const products = data?.products;
|
|
1842
|
+
for (const p of Array.isArray(products) ? products : []) {
|
|
1843
|
+
for (const s of Array.isArray(p?.skus) ? p.skus : []) {
|
|
1844
|
+
const raw = field === "discount" ? s?.discount : s?.activity_price?.amount;
|
|
1845
|
+
const id = String(s?.id);
|
|
1846
|
+
if (!out2.has(id)) out2.set(id, raw === void 0 || raw === null || raw === "" ? void 0 : String(raw));
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1849
|
+
return out2;
|
|
1850
|
+
}
|
|
1851
|
+
function productLimitsOf(data) {
|
|
1852
|
+
const out2 = /* @__PURE__ */ new Map();
|
|
1853
|
+
const products = data?.products;
|
|
1854
|
+
for (const p of Array.isArray(products) ? products : []) {
|
|
1855
|
+
if (typeof p?.quantity_limit === "number" && typeof p?.quantity_per_user === "number") out2.set(String(p.id), [p.quantity_limit, p.quantity_per_user]);
|
|
1856
|
+
}
|
|
1857
|
+
return out2;
|
|
1858
|
+
}
|
|
1859
|
+
function lostText(pre, rb, field) {
|
|
1860
|
+
const parts = [];
|
|
1861
|
+
const rbProducts = Array.isArray(rb?.products) ? rb.products : [];
|
|
1862
|
+
const rbProd = new Map(rbProducts.map((p) => [String(p?.id), p]));
|
|
1863
|
+
const rbVals = existingSkuValues(rb, field);
|
|
1864
|
+
const rbHas = new Set(rbProducts.flatMap((p) => (Array.isArray(p?.skus) ? p.skus : []).map((s) => String(s?.id))));
|
|
1865
|
+
const preVals = existingSkuValues(pre, field);
|
|
1866
|
+
for (const p of Array.isArray(pre?.products) ? pre.products : []) {
|
|
1867
|
+
for (const s of Array.isArray(p?.skus) ? p.skus : []) {
|
|
1868
|
+
const sid = String(s?.id);
|
|
1869
|
+
if (!rbHas.has(sid)) {
|
|
1870
|
+
parts.push(`\u539F\u6709 ${sid} \u7F3A\u5931`);
|
|
1871
|
+
continue;
|
|
1872
|
+
}
|
|
1873
|
+
const was = preVals.get(sid), now = rbVals.get(sid);
|
|
1874
|
+
if (was !== void 0 && (now === void 0 || Number(now) !== Number(was))) parts.push(`\u539F\u6709 ${sid} \u503C\u53D8\u4E86\uFF08\u539F ${was}\uFF0C\u73B0 ${now ?? "\u65E0"}\uFF09`);
|
|
1875
|
+
}
|
|
1876
|
+
const q = rbProd.get(String(p?.id));
|
|
1877
|
+
if (!q) continue;
|
|
1878
|
+
if (typeof p?.quantity_limit === "number" && typeof p?.quantity_per_user === "number" && (q.quantity_limit !== p.quantity_limit || q.quantity_per_user !== p.quantity_per_user)) {
|
|
1879
|
+
parts.push(`\u539F\u6709\u5546\u54C1 ${p.id} \u9650\u8D2D\u53D8\u4E86\uFF08\u539F ${p.quantity_limit}/${p.quantity_per_user}\uFF0C\u73B0 ${q.quantity_limit}/${q.quantity_per_user}\uFF09`);
|
|
1880
|
+
}
|
|
1881
|
+
}
|
|
1882
|
+
return parts.join("\uFF1B");
|
|
1883
|
+
}
|
|
1884
|
+
function validateAddProducts(ctx2) {
|
|
1885
|
+
const { args: args2, rest } = ctx2;
|
|
1886
|
+
for (const k of Object.keys(args2)) {
|
|
1887
|
+
if (k === "activity-id") return { ok: false, message: ADD_TEXT.AV2 };
|
|
1888
|
+
}
|
|
1889
|
+
for (const k of Object.keys(args2)) {
|
|
1890
|
+
if (ADD_PRODUCTS_FLAGS.includes(k)) continue;
|
|
1891
|
+
const own = ADD_PRODUCTS_FLAGS.filter((f) => !GLOBAL_FLAGS.includes(f));
|
|
1892
|
+
const hint = suggestFlag(k, own, args2[k], Date.now(), "promotions add-products");
|
|
1893
|
+
const tip = !hint ? "" : hint.startsWith("--") ? `\uFF08\u4F60\u662F\u60F3\u7528 ${hint} \u5417\uFF1F\uFF09` : `\uFF08${hint}\uFF09`;
|
|
1894
|
+
return { ok: false, message: `\u4E0D\u652F\u6301\u7684\u53C2\u6570 --${k}${tip}\uFF1B\u672C\u547D\u4EE4\u53EA\u8BA4 ${ADD_PRODUCTS_FLAGS.map((f) => "--" + f).join(" ")}` };
|
|
1895
|
+
}
|
|
1896
|
+
const v3flag = "price" in args2 ? "price" : discountValueFlag(args2);
|
|
1897
|
+
if (rest && rest.length > 0) return { ok: false, message: ADD_TEXT.AV3(rest.join(" "), v3flag) };
|
|
1898
|
+
if ("price" in args2 && "percent" in args2) {
|
|
1899
|
+
return { ok: false, message: "--price \u4E0E --percent \u53EA\u80FD\u4E8C\u9009\u4E00\uFF1A\u4E00\u53E3\u4EF7\u7528 --price\uFF0C\u767E\u5206\u6BD4\u6298\u6263\u7528 --percent\u3002" };
|
|
1900
|
+
}
|
|
1901
|
+
if (!("price" in args2) && !("percent" in args2)) {
|
|
1902
|
+
return { ok: false, message: `--price \u5FC5\u586B\uFF08\u767E\u5206\u6BD4\u6298\u6263\u6539\u7528 --percent\uFF0C\u4E24\u8005\u4E8C\u9009\u4E00\uFF09\uFF0C\u4E14\u5FC5\u987B\u5E26\u503C\uFF08\u53EA\u5199 --price \u4E0D\u7ED9\u503C\u4F1A\u88AB\u89E3\u6790\u6210\u5B57\u7B26\u4E32 "true"\uFF0C\u5199\u6210 --price= \u5219\u662F\u7A7A\u503C\uFF0C\u4E24\u79CD\u90FD\u4E0D\u7B97\uFF09` };
|
|
1903
|
+
}
|
|
1904
|
+
if (!args2.id || args2.id === "true" || !args2.id.trim()) {
|
|
1905
|
+
return { ok: false, message: `--id \u5FC5\u586B\uFF0C\u4E14\u5FC5\u987B\u5E26\u503C\uFF08\u6D3B\u52A8 id\uFF0C\u7EAF\u6570\u5B57\uFF0C\u5982 --id 7686081985965900001\uFF09` };
|
|
1906
|
+
}
|
|
1907
|
+
if (!/^\d+$/.test(args2.id)) {
|
|
1908
|
+
return { ok: false, message: `--id \u5FC5\u987B\u662F\u7EAF\u6570\u5B57\u7684\u6D3B\u52A8 id\uFF08\u6536\u5230\u300C${args2.id}\u300D\uFF09` };
|
|
1909
|
+
}
|
|
1910
|
+
const flag = discountValueFlag(args2);
|
|
1911
|
+
const val = flag === "percent" ? args2.percent : args2.price;
|
|
1912
|
+
if (!val || val === "true" || !val.trim()) {
|
|
1913
|
+
return { ok: false, message: `--${flag} \u5FC5\u586B\uFF0C\u4E14\u5FC5\u987B\u5E26\u503C\uFF08\u53EA\u5199 --${flag} \u4E0D\u7ED9\u503C\u4F1A\u88AB\u89E3\u6790\u6210\u5B57\u7B26\u4E32 "true"\uFF0C\u5199\u6210 --${flag}= \u5219\u662F\u7A7A\u503C\uFF0C\u4E24\u79CD\u90FD\u4E0D\u7B97\uFF09` };
|
|
1914
|
+
}
|
|
1915
|
+
if ("product" in args2 && (!args2.product || args2.product === "true")) {
|
|
1916
|
+
return { ok: false, message: `--product \u5FC5\u586B\uFF0C\u4E14\u5FC5\u987B\u5E26\u503C\uFF08\u53EA\u5199 --product \u4E0D\u7ED9\u503C\u4F1A\u88AB\u89E3\u6790\u6210\u5B57\u7B26\u4E32 "true"\uFF0C\u5199\u6210 --product= \u5219\u662F\u7A7A\u503C\uFF0C\u4E24\u79CD\u90FD\u4E0D\u7B97\uFF09` };
|
|
1917
|
+
}
|
|
1918
|
+
if (args2.product?.includes(",")) {
|
|
1919
|
+
return { ok: false, message: `--product \u53EA\u6536\u4E00\u4E2A\u5546\u54C1 id\uFF1B\u591A\u5546\u54C1\u8BF7\u5728 --${flag} \u91CC\u5199 <productId>/<skuId>:${flag === "percent" ? "<\u51CFN%>" : "<\u4EF7>"}` };
|
|
1920
|
+
}
|
|
1921
|
+
const parsed = parsePriceItems(val, args2.product, flag);
|
|
1922
|
+
if (!parsed.ok) return parsed;
|
|
1923
|
+
return { ok: true };
|
|
1924
|
+
}
|
|
1925
|
+
function addProductsPlan(id, flag, raw, product) {
|
|
1926
|
+
const parsed = parsePriceItems(raw, product, flag);
|
|
1927
|
+
const items = parsed.ok ? parsed.items : [];
|
|
1928
|
+
return [
|
|
1929
|
+
{ step: "1/3 \u9884\u8BFB\u6D3B\u52A8", method: "GET", path: `/promotion/202309/activities/${id}` },
|
|
1930
|
+
{
|
|
1931
|
+
step: flag === "percent" ? "2/3 \u52A0\u5546\u54C1+\u51CFN%" : "2/3 \u52A0\u5546\u54C1+\u4E00\u53E3\u4EF7",
|
|
1932
|
+
method: "PUT",
|
|
1933
|
+
path: `/promotion/202309/activities/${id}/products`,
|
|
1934
|
+
body: { activity_id: id, ...productsBodyFromItems(items, flag) },
|
|
1935
|
+
human: ADD_TEXT.HUMAN_ADD(id, discountItemsHuman(items, flag))
|
|
1936
|
+
},
|
|
1937
|
+
{ step: "3/3 \u56DE\u8BFB", method: "GET", path: `/promotion/202309/activities/${id}` }
|
|
1938
|
+
];
|
|
1939
|
+
}
|
|
1940
|
+
async function runAddProducts(shop, id, flag, raw, product) {
|
|
1941
|
+
const parsed = parsePriceItems(raw, product, flag);
|
|
1942
|
+
const items = parsed.ok ? parsed.items : [];
|
|
1943
|
+
const field = flag === "percent" ? "discount" : "amount";
|
|
1944
|
+
const submitted = items.map((it) => ({ sid: it.sid, amount: it.amount }));
|
|
1945
|
+
const reject = (message, meta) => ({ ok: false, error: { code: "VALIDATION", message, retryable: false }, ...meta ? { meta } : {} });
|
|
1946
|
+
const pre = await proxy("GET", shop, `/promotion/202309/activities/${id}`, {});
|
|
1947
|
+
if (!pre.ok) {
|
|
1948
|
+
const err = pre.error;
|
|
1949
|
+
const status = pre.meta?.http_status;
|
|
1950
|
+
const transient = status === void 0 || status >= 500 || err.code === "RATE_LIMITED";
|
|
1951
|
+
return { ...pre, error: { ...err, message: `${err.message} ${transient ? ADD_TEXT.AP1N(id) : ADD_TEXT.AP1(shop, id)}` } };
|
|
1952
|
+
}
|
|
1953
|
+
const d = pre.data ?? {};
|
|
1954
|
+
if (typeof d.activity_type !== "string" || !Array.isArray(d.products)) return reject(ADD_TEXT.AP1M(shop, id), pre.meta);
|
|
1955
|
+
const type = String(d.activity_type);
|
|
1956
|
+
if (type === "FIXED_PRICE" && flag === "percent") return reject(ADD_TEXT.AT1(id), pre.meta);
|
|
1957
|
+
if (type === "DIRECT_DISCOUNT" && flag === "price") return reject(ADD_TEXT.AT2(id), pre.meta);
|
|
1958
|
+
if (type === "FLASHSALE") return reject(ADD_TEXT.AT3(id), pre.meta);
|
|
1959
|
+
if (type !== "FIXED_PRICE" && type !== "DIRECT_DISCOUNT") return reject(ADD_TEXT.AT4(id, type), pre.meta);
|
|
1960
|
+
if (!ADD_ALLOWED_STATUS.includes(String(d.status))) return reject(ADD_TEXT.AS1(id, String(d.status), ADD_ALLOWED_STATUS.join(" / ")), pre.meta);
|
|
1961
|
+
if (d.product_level !== "VARIATION") return reject(ADD_TEXT.AL1(id, String(d.product_level)), pre.meta);
|
|
1962
|
+
const existing = existingSkuValues(d, field);
|
|
1963
|
+
const same = [], diff = [];
|
|
1964
|
+
const rest = [];
|
|
1965
|
+
for (const it of items) {
|
|
1966
|
+
if (!existing.has(it.sid)) {
|
|
1967
|
+
rest.push(it);
|
|
1968
|
+
continue;
|
|
1969
|
+
}
|
|
1970
|
+
const cur = existing.get(it.sid);
|
|
1971
|
+
if (cur !== void 0 && Number(cur) === Number(it.amount)) same.push(it.sid);
|
|
1972
|
+
else diff.push(it.sid);
|
|
1973
|
+
}
|
|
1974
|
+
const restCmd = addProductsCmd(shop, id, product, flag, rawItemsFor(raw, rest.map((r) => r.sid)), true);
|
|
1975
|
+
if (diff.length) return reject(ADD_TEXT.AD1(id, diff.join("\u3001")) + (rest.length ? ADD_TEXT.AD1_REST(restCmd) : ""), pre.meta);
|
|
1976
|
+
if (rest.length === 0) {
|
|
1977
|
+
return { ok: true, data: { activity_id: id, readback: pre.data, note: ADD_TEXT.AD3(items.length, id) }, meta: pre.meta };
|
|
1978
|
+
}
|
|
1979
|
+
if (same.length) return reject(ADD_TEXT.AD2(id, same.join("\u3001"), restCmd), pre.meta);
|
|
1980
|
+
const body = { activity_id: id, ...productsBodyFromItems(items, flag, productLimitsOf(d)) };
|
|
1981
|
+
const put = await proxy("PUT", shop, `/promotion/202309/activities/${id}/products`, { body });
|
|
1982
|
+
const rb = await proxy("GET", shop, `/promotion/202309/activities/${id}`, {});
|
|
1983
|
+
const readback = rb.ok ? rb.data : { error: rb.error };
|
|
1984
|
+
const c = rb.ok ? compareReadback(submitted, rb.data, field) : null;
|
|
1985
|
+
const lost = c ? lostText(d, rb.data, field) : "";
|
|
1986
|
+
const missingCmd = (apply) => addProductsCmd(shop, id, product, flag, rawItemsFor(raw, c?.missing ?? []), apply);
|
|
1987
|
+
if (!put.ok) {
|
|
1988
|
+
const { retry_after_s: _dropped, ...err } = put.error;
|
|
1989
|
+
let note;
|
|
1990
|
+
if (!c) note = ADD_TEXT.AN4(shop, id);
|
|
1991
|
+
else if (c.missing.length === 0 && c.mismatched.length === 0) note = ADD_TEXT.AN1(submitted.length, id);
|
|
1992
|
+
else if (c.missing.length === submitted.length) note = ADD_TEXT.AN2(id);
|
|
1993
|
+
else note = ADD_TEXT.AN3(problemsText(c, field)) + (c.missing.length ? ADD_TEXT.AN3_MISS(missingCmd(false)) : "") + (c.mismatched.length ? ADD_TEXT.AN3_MIS : "");
|
|
1994
|
+
if (lost) note += " " + ADD_TEXT.AW3(shop, id, lost);
|
|
1995
|
+
return { ok: false, error: { ...err, retryable: false }, data: { activity_id: id, readback, note }, meta: put.meta };
|
|
1996
|
+
}
|
|
1997
|
+
const ours = [];
|
|
1998
|
+
if (!c) ours.push(ADD_TEXT.AW1(shop, id));
|
|
1999
|
+
else {
|
|
2000
|
+
const problems = problemsText(c, field);
|
|
2001
|
+
if (problems) ours.push(ADD_TEXT.AW2(id, problems) + (c.missing.length ? ADD_TEXT.AW2_MISS(missingCmd(true)) : ""));
|
|
2002
|
+
if (lost) ours.push(ADD_TEXT.AW3(shop, id, lost));
|
|
2003
|
+
}
|
|
2004
|
+
const putData = put.data ?? {};
|
|
2005
|
+
const data = { ...putData, activity_id: id, readback };
|
|
2006
|
+
if (ours.length > 0) data.warnings = mergeWarnings(putData.warnings, ours);
|
|
2007
|
+
return { ok: true, data, meta: put.meta };
|
|
1711
2008
|
}
|
|
1712
2009
|
|
|
1713
2010
|
// src/index.ts
|