@posx/core 5.5.586 → 5.5.589

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.
Files changed (58) hide show
  1. package/CLAUDE.md +23 -23
  2. package/LICENSE +21 -21
  3. package/README.md +85 -85
  4. package/build/index.d.ts +83 -5
  5. package/build/index.js +4 -4
  6. package/dev/.stfolder/syncthing-folder-9a95b7.txt +5 -0
  7. package/dev/98894488.xlsx +0 -0
  8. package/dev/HappyThaiSembawang.csv +336 -0
  9. package/dev/KB/create-new-model.md +34 -0
  10. package/dev/KB/markdown-lint.md +14 -0
  11. package/dev/KB/object-clone-pitfalls.md +52 -0
  12. package/dev/KB/readmefirst.md +8 -0
  13. package/dev/KB/stock-deduction-logic.md +61 -0
  14. package/dev/Merchants/HappyThaiSembawang.csv +400 -0
  15. package/dev/Merchants/HappyThaiSembawang.xlsx +0 -0
  16. package/dev/Merchants/charen_thai/category.csv +20 -0
  17. package/dev/Merchants/charen_thai/charen_thai_xpos.csv +1021 -0
  18. package/dev/Merchants/charen_thai/convert.cjs +194 -0
  19. package/dev/Merchants/charen_thai/item.csv +183 -0
  20. package/dev/Merchants/charen_thai/modifier.csv +664 -0
  21. package/dev/Product_Import_Template.xlsx +0 -0
  22. package/dev/XPOS Invoice Module.pdf +232 -0
  23. package/dev/convert_menu.cjs +134 -0
  24. package/dev/convert_menu.py +127 -0
  25. package/dev/data/invoice.json +1 -0
  26. package/dev/escpos/receipt.bin +0 -0
  27. package/dev/escpos/receipt.hex +1 -0
  28. package/dev/escpos/receipt.json +1 -0
  29. package/dev/escpos-cli-usage.md +103 -0
  30. package/dev/export/xpos_menu.csv +1021 -0
  31. package/dev/export/xpos_menu_bilingual.csv +1021 -0
  32. package/dev/export/xpos_retail_sample.csv +38 -0
  33. package/dev/harbor-harness-deployment.md +78 -0
  34. package/dev/incidents/2026-04-01-reprint-timeout.md +33 -0
  35. package/dev/incidents/2026-05-06-searchable-field-design-pitfall.md +37 -0
  36. package/dev/nginx-harbor-harness.conf +84 -0
  37. package/dev/px-cli.md +97 -0
  38. package/dev/test-logs/2026-02.md +5 -0
  39. package/dev/tmp/xpos_product_import(1).csv +338 -0
  40. package/dev/tmp/xpos_product_import_fixed.csv +338 -0
  41. package/dev//344/272/247/345/223/201/345/257/274/345/205/245/346/250/241/346/235/277.xlsx +0 -0
  42. package/jest.config.cjs +36 -36
  43. package/jest.setup.cjs +91 -91
  44. package/package.json +1 -1
  45. package/package.publish.json +121 -121
  46. package/tsdown.config.ts +21 -21
  47. package/vite.config.ts +86 -86
  48. package/AGENTS.md +0 -24
  49. package/memo/technical-docs/01_ARCHITECTURE.md +0 -147
  50. package/memo/technical-docs/02_CORE_BUSINESS.md +0 -292
  51. package/memo/technical-docs/03_UI_COMPONENTS.md +0 -59
  52. package/memo/technical-docs/04_VIEWS.md +0 -82
  53. package/memo/technical-docs/05_DATA_LAYER.md +0 -375
  54. package/memo/technical-docs/06_CROSS_PLATFORM.md +0 -246
  55. package/memo/technical-docs/07_SIMILARITY_INDEX.md +0 -195
  56. package/memo/technical-docs/CHECKPOINT.md +0 -46
  57. package/memo/technical-docs/PROJECT_OVERVIEW.md +0 -122
  58. package/memo/technical-docs/TECHNICAL_DOCS_PLAN.md +0 -77
@@ -0,0 +1,38 @@
1
+ Type,Name,SKU,Price,Stock,Is Internal,Min Order,Max Order,Image URL,Thumbnail URL,Sequence,Item UID,Print On Receipt,Discountable,Open Editor Panel,Is Delisted,Name Translations,Prices,PLU,Code
2
+ category,Electronics,,,,,false,,,,,1,,,,,false,en:Electronics|zh:电子产品|vi:Điện tử,,001
3
+ subcategory,Smartphones,,,,,false,,,,,0,,,,,false,en:Smartphones|zh:智能手机|vi:Điện thoại,,001-01
4
+ product,iPhone 15 Pro,IP15PRO,1599.00,50,false,1,5,,,0,itm_ip15pro,true,true,false,false,en:iPhone 15 Pro|zh:iPhone 15 Pro|vi:iPhone 15 Pro,,PLU001,
5
+ product,Samsung Galaxy S24,SGS24,1299.00,35,false,1,5,,,1,itm_sgs24,true,true,false,false,en:Samsung Galaxy S24|zh:三星 Galaxy S24|vi:Samsung Galaxy S24,,PLU002,
6
+ product,Xiaomi 14,XM14,899.00,60,false,1,10,,,2,itm_xm14,true,true,false,false,en:Xiaomi 14|zh:小米 14|vi:Xiaomi 14,,PLU003,
7
+ subcategory,Tablets,,,,,false,,,,,1,,,,,false,en:Tablets|zh:平板电脑|vi:Máy tính bảng,,001-02
8
+ product,iPad Pro 12.9,IPADPRO,1799.00,20,false,1,3,,,0,itm_ipadpro,true,true,false,false,en:iPad Pro 12.9|zh:iPad Pro 12.9|vi:iPad Pro 12.9,,PLU004,
9
+ product,Samsung Galaxy Tab S9,TABS9,1099.00,25,false,1,5,,,1,itm_tabs9,true,true,false,false,en:Samsung Galaxy Tab S9|zh:三星 Galaxy Tab S9|vi:Samsung Galaxy Tab S9,,PLU005,
10
+ subcategory,Accessories,,,,,false,,,,,2,,,,,false,en:Accessories|zh:配件|vi:Phụ kiện,,001-03
11
+ product,AirPods Pro 2,APP2,349.00,100,false,1,10,,,0,itm_app2,true,true,false,false,en:AirPods Pro 2|zh:AirPods Pro 2|vi:AirPods Pro 2,,PLU006,
12
+ product,Apple Watch Ultra 2,AWU2,1199.00,30,false,1,5,,,1,itm_awu2,true,true,false,false,en:Apple Watch Ultra 2|zh:Apple Watch Ultra 2|vi:Apple Watch Ultra 2,,PLU007,
13
+ product,USB-C Charger 65W,USBC65,45.00,200,false,1,20,,,2,itm_usbc65,true,true,false,false,en:USB-C Charger 65W|zh:USB-C 65W充电器|vi:Sạc USB-C 65W,,PLU008,
14
+ category,Apparel,,,,,false,,,,,2,,,,,false,en:Apparel|zh:服装|vi:Quần áo,,002
15
+ subcategory,Men,,,,,false,,,,,0,,,,,false,en:Men|zh:男装|vi:Nam,,002-01
16
+ product,Cotton T-Shirt White,TSHIRT-W-M,29.90,150,false,1,10,,,0,itm_tshirt_wm,true,true,false,false,en:Cotton T-Shirt White|zh:白色纯棉T恤|vi:Áo thun cotton trắng,"[{""lookup_keys"":[""S""],""amount"":29.90,""name"":""S""},{""lookup_keys"":[""M""],""amount"":29.90,""name"":""M""},{""lookup_keys"":[""L""],""amount"":29.90,""name"":""L""},{""lookup_keys"":[""XL""],""amount"":32.90,""name"":""XL""}]",PLU009,
17
+ product,Denim Jeans Slim,JEANS-S-M,89.90,80,false,1,5,,,1,itm_jeans_sm,true,true,false,false,en:Denim Jeans Slim|zh:修身牛仔裤|vi:Quần jeans ôm,"[{""lookup_keys"":[""30""],""amount"":89.90,""name"":""30""},{""lookup_keys"":[""32""],""amount"":89.90,""name"":""32""},{""lookup_keys"":[""34""],""amount"":89.90,""name"":""34""},{""lookup_keys"":[""36""],""amount"":94.90,""name"":""36""}]",PLU010,
18
+ product,Running Shoes Pro,RUNPRO-M,159.00,45,false,1,3,,,2,itm_runpro_m,true,true,false,false,en:Running Shoes Pro|zh:专业跑鞋|vi:Giày chạy bộ Pro,"[{""lookup_keys"":[""40""],""amount"":159.00,""name"":""40""},{""lookup_keys"":[""41""],""amount"":159.00,""name"":""41""},{""lookup_keys"":[""42""],""amount"":159.00,""name"":""42""},{""lookup_keys"":[""43""],""amount"":159.00,""name"":""43""},{""lookup_keys"":[""44""],""amount"":164.00,""name"":""44""}]",PLU011,
19
+ subcategory,Women,,,,,false,,,,,1,,,,,false,en:Women|zh:女装|vi:Nữ,,002-02
20
+ product,Summer Dress Floral,DRESS-F-W,79.90,60,false,1,5,,,0,itm_dress_fw,true,true,false,false,en:Summer Dress Floral|zh:碎花夏裙|vi:Váy hoa mùa hè,"[{""lookup_keys"":[""S""],""amount"":79.90,""name"":""S""},{""lookup_keys"":[""M""],""amount"":79.90,""name"":""M""},{""lookup_keys"":[""L""],""amount"":79.90,""name"":""L""}]",PLU012,
21
+ product,Yoga Leggings,YOGA-W,59.90,90,false,1,5,,,1,itm_yoga_w,true,true,false,false,en:Yoga Leggings|zh:瑜伽裤|vi:Quần legging yoga,"[{""lookup_keys"":[""S""],""amount"":59.90,""name"":""S""},{""lookup_keys"":[""M""],""amount"":59.90,""name"":""M""},{""lookup_keys"":[""L""],""amount"":59.90,""name"":""L""}]",PLU013,
22
+ category,Home & Living,,,,,false,,,,,3,,,,,false,en:Home & Living|zh:家居生活|vi:Nhà & Đời sống,,003
23
+ product,LED Desk Lamp,LEDLAMP,49.90,75,false,1,10,,,0,itm_ledlamp,true,true,false,false,en:LED Desk Lamp|zh:LED台灯|vi:Đèn bàn LED,,PLU014,
24
+ product,Ceramic Mug Set 4pcs,MUGSET4,35.00,120,false,1,10,,,1,itm_mugset4,true,true,false,false,en:Ceramic Mug Set 4pcs|zh:陶瓷杯4件套|vi:Bộ cốc gốm 4 chiếc,,PLU015,
25
+ product,Memory Foam Pillow,MFPILLOW,69.00,50,false,1,5,,,2,itm_mfpillow,true,true,false,false,en:Memory Foam Pillow|zh:记忆棉枕头|vi:Gối memory foam,,PLU016,
26
+ product,Stainless Steel Bottle,SSBOTTLE,25.00,200,false,1,20,,,3,itm_ssbottle,true,true,false,false,en:Stainless Steel Bottle|zh:不锈钢保温杯|vi:Bình inox,,PLU017,
27
+ category,Groceries,,,,,false,,,,,4,,,,,false,en:Groceries|zh:杂货|vi:Tạp hóa,,004
28
+ product,Organic Honey 500g,HONEY500,18.90,80,false,1,10,,,0,itm_honey500,true,true,false,false,en:Organic Honey 500g|zh:有机蜂蜜500g|vi:Mật ong hữu cơ 500g,,PLU018,
29
+ product,Extra Virgin Olive Oil 1L,EVOO1L,24.90,60,false,1,5,,,1,itm_evoo1l,true,true,false,false,en:Extra Virgin Olive Oil 1L|zh:特级初榨橄榄油1L|vi:Dầu olive extra virgin 1L,,PLU019,
30
+ product,Premium Coffee Beans 1kg,COFFEE1K,32.00,100,false,1,10,,,2,itm_coffee1k,true,true,false,false,en:Premium Coffee Beans 1kg|zh:精品咖啡豆1kg|vi:Cà phê hạt cao cấp 1kg,,PLU020,
31
+ product,Green Tea 100 bags,GTEA100,12.90,150,false,1,20,,,3,itm_gtea100,true,true,false,false,en:Green Tea 100 bags|zh:绿茶100包|vi:Trà xanh 100 túi,,PLU021,
32
+ product,Dark Chocolate 200g,CHOCO200,8.90,200,false,1,30,,,4,itm_choco200,true,true,false,false,en:Dark Chocolate 200g|zh:黑巧克力200g|vi:Socola đen 200g,,PLU022,
33
+ category,Sports & Outdoors,,,,,false,,,,,5,,,,,false,en:Sports & Outdoors|zh:运动户外|vi:Thể thao & Ngoài trời,,005
34
+ product,Yoga Mat Premium,YOGAMAT,45.00,70,false,1,5,,,0,itm_yogamat,true,true,false,false,en:Yoga Mat Premium|zh:高端瑜伽垫|vi:Thảm yoga cao cấp,,PLU023,
35
+ product,Resistance Bands Set,RBAND,29.90,90,false,1,10,,,1,itm_rband,true,true,false,false,en:Resistance Bands Set|zh:阻力带套装|vi:Bộ dây kháng lực,,PLU024,
36
+ product,Jump Rope Pro,JUMPROPE,19.90,100,false,1,10,,,2,itm_jumprope,true,true,false,false,en:Jump Rope Pro|zh:专业跳绳|vi:Dây nhảy chuyên nghiệp,,PLU025,
37
+ product,Camping Tent 2P,TENT2P,199.00,25,false,1,3,,,3,itm_tent2p,true,true,false,false,en:Camping Tent 2P|zh:双人帐篷|vi:Lều cắm trại 2 người,,PLU026,
38
+ product,Hiking Backpack 40L,HKBP40L,129.00,40,false,1,5,,,4,itm_hkbp40l,true,true,false,false,en:Hiking Backpack 40L|zh:40L登山背包|vi:Ba lô leo núi 40L,,PLU027,
@@ -0,0 +1,78 @@
1
+ # Harbor + Harness 部署总结
2
+
3
+ ## 服务端口
4
+
5
+ | 服务 | 端口 | 说明 |
6
+ |-------------|------|----------------|
7
+ | Harbor | 8081 | 容器镜像仓库 |
8
+ | Harness | 8082 | Git 代码托管 |
9
+ | Harness SSH | 3022 | Git SSH |
10
+ | PostgreSQL | 5433 | 数据库 |
11
+ | Redis | 6380 | 缓存 |
12
+
13
+ ## 外部访问
14
+
15
+ | 服务 | 外部地址 | 内部地址 |
16
+ |---------|-------------------------|--------------|
17
+ | Harbor | https://harbor.wyo.sg | LAN_IP:8081 |
18
+ | Harness | https://harness.wyo.sg | LAN_IP:8082 |
19
+
20
+ ## Harbor 登录
21
+
22
+ - URL: https://harbor.wyo.sg
23
+ - 用户名: `admin`
24
+ - 密码: `Harbor@2024!`
25
+
26
+ ## Harness 登录
27
+
28
+ - URL: https://harness.wyo.sg
29
+ - 用户名: `admin@harness.local`
30
+ - 密码: `Harness@2024!`
31
+
32
+ ## PostgreSQL
33
+
34
+ Host: `127.0.0.1:5433`
35
+
36
+ | 数据库 | 用户名 | 密码 |
37
+ |----------|----------|----------------|
38
+ | postgres | postgres | Postgres@2024! |
39
+ | harbor | harbor | Harbor@2024! |
40
+ | harness | harness | Harness@2024! |
41
+
42
+ ## Redis
43
+
44
+ - Host: `127.0.0.1:6380`
45
+ - 密码: (无)
46
+ - Harbor DB Index: 1, 2, 5, 6, 7
47
+
48
+ ## 文件位置
49
+
50
+ ```
51
+ /opt/infra/docker-compose.yml # PostgreSQL + Redis
52
+ /opt/infra/config/postgresql.conf # PostgreSQL 配置
53
+ /opt/infra/config/redis.conf # Redis 配置
54
+ /opt/harbor/harbor.yml # Harbor 配置
55
+ /opt/harness/docker-compose.yml # Harness 配置
56
+ ```
57
+
58
+ ## 管理命令
59
+
60
+ ```bash
61
+ # 基础设施
62
+ cd /opt/infra && docker compose up -d
63
+ cd /opt/infra && docker compose down
64
+
65
+ # Harbor
66
+ cd /opt/harbor && docker compose up -d
67
+ cd /opt/harbor && docker compose down
68
+
69
+ # Harness
70
+ cd /opt/harness && docker compose up -d
71
+ cd /opt/harness && docker compose down
72
+ ```
73
+
74
+ ## Docker 登录 Harbor
75
+
76
+ ```bash
77
+ docker login harbor.wyo.sg
78
+ ```
@@ -0,0 +1,33 @@
1
+ # Incident: 重打收据超时失败
2
+
3
+ - **日期:** 2026-04-01
4
+ - **Issue:** #91
5
+ - **Commit:** `441ec0c`
6
+ - **影响范围:** 所有超过 1 小时的订单重打收据/厨房单
7
+
8
+ ## 现象
9
+
10
+ 用户在 12:27 重打一张 07:54 创建的订单收据,打印机无响应,PrintJob 被 worker 直接标记为 Failed。
11
+
12
+ ## 根因
13
+
14
+ `reprintReceipt()` 和 `printLastKitchenSlips()` 从 DB 取出原始 PrintJob 复用,重置了 `uid`, `status`, `retries` 等字段,但**遗漏了 `created_at_timestamp`**。
15
+
16
+ 新 job 携带原始订单的创建时间 (07:54),被 App 端 worker 的超时逻辑判定为超过 1 小时,直接标记 Failed。
17
+
18
+ ```
19
+ 原始 PrintJob (07:54) → 复制 → 换 uid → 重置 status=Queued
20
+ ❌ created_at_timestamp 仍为 07:54
21
+ → worker: 距今 > 1h → Failed
22
+ ```
23
+
24
+ ## 修复
25
+
26
+ 在两处 clone 路径中重置时间戳:
27
+
28
+ - `invoice.service.ts` `reprintReceipt()`: `printJob.created_at_timestamp = Date.now()`
29
+ - `invoice.service.ts` `printLastKitchenSlips()`: `updatedJob.created_at_timestamp = Date.now()`
30
+
31
+ ## 相关知识
32
+
33
+ - [对象复用的隐式状态泄漏](../KB/object-clone-pitfalls.md)
@@ -0,0 +1,37 @@
1
+ # Boolean 字段默认值设计陷阱
2
+
3
+ **日期:** 2026-05-06
4
+ **类型:** 设计审查
5
+ **严重程度:** 高(若未发现会导致生产事故)
6
+
7
+ ## 问题描述
8
+
9
+ 在为 Category 和 Item 添加 `is_searchable` 字段时,若设计为:
10
+ - `is_searchable: boolean` 默认 `true`
11
+
12
+ 会导致兼容性问题:
13
+ - 现有数据库记录没有此字段
14
+ - JavaScript 读取时值为 `undefined`
15
+ - `undefined` 是 falsy,逻辑上等同于 `false`
16
+ - **结果:所有现有 item/category 突然变得不可搜索**
17
+
18
+ ## 正确方案
19
+
20
+ 使用**反向布尔字段**:`is_not_searchable`
21
+ - 默认值:`false`(可搜索)
22
+ - 现有数据无此字段 = `undefined` = falsy = 可搜索
23
+ - 显式设为 `true` 才会排除搜索
24
+
25
+ ## 通用规则
26
+
27
+ 新增布尔字段时,确保:
28
+ - `undefined`/缺失值 = 系统原有行为
29
+ - 新行为需要显式设置 `true`
30
+
31
+ **命名模式:**
32
+ - 原行为是 X → 新字段应为 `is_not_X` 或 `disable_X`
33
+ - 这样 `undefined` = 保持原行为
34
+
35
+ ## 相关文件
36
+
37
+ - `src/types/product.type.ts` - ICategory, IItem 接口
@@ -0,0 +1,84 @@
1
+ # Harbor - 容器镜像仓库
2
+ server {
3
+ listen 80;
4
+ server_name harbor.wyo.sg;
5
+ return 301 https://$server_name$request_uri;
6
+ }
7
+
8
+ server {
9
+ listen 443 ssl http2;
10
+ server_name harbor.wyo.sg;
11
+
12
+ ssl_certificate /etc/nginx/ssl/wyo.sg/fullchain.pem;
13
+ ssl_certificate_key /etc/nginx/ssl/wyo.sg/privkey.pem;
14
+
15
+ # SSL 配置
16
+ ssl_protocols TLSv1.2 TLSv1.3;
17
+ ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
18
+ ssl_prefer_server_ciphers off;
19
+ ssl_session_cache shared:SSL:10m;
20
+ ssl_session_timeout 1d;
21
+
22
+ # 重要:Docker 镜像上传无大小限制
23
+ client_max_body_size 0;
24
+ chunked_transfer_encoding on;
25
+
26
+ # 禁用缓冲,支持大文件流式传输
27
+ proxy_buffering off;
28
+ proxy_request_buffering off;
29
+
30
+ location / {
31
+ proxy_pass http://LAN_IP:8081;
32
+ proxy_set_header Host $host;
33
+ proxy_set_header X-Real-IP $remote_addr;
34
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
35
+ proxy_set_header X-Forwarded-Proto $scheme;
36
+
37
+ # 超时设置(镜像推送可能耗时较长)
38
+ proxy_connect_timeout 900;
39
+ proxy_send_timeout 900;
40
+ proxy_read_timeout 900;
41
+ }
42
+ }
43
+
44
+ # Harness - Git 代码托管
45
+ server {
46
+ listen 80;
47
+ server_name harness.wyo.sg;
48
+ return 301 https://$server_name$request_uri;
49
+ }
50
+
51
+ server {
52
+ listen 443 ssl http2;
53
+ server_name harness.wyo.sg;
54
+
55
+ ssl_certificate /etc/nginx/ssl/wyo.sg/fullchain.pem;
56
+ ssl_certificate_key /etc/nginx/ssl/wyo.sg/privkey.pem;
57
+
58
+ ssl_protocols TLSv1.2 TLSv1.3;
59
+ ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
60
+ ssl_prefer_server_ciphers off;
61
+ ssl_session_cache shared:SSL:10m;
62
+ ssl_session_timeout 1d;
63
+
64
+ # Git 仓库可能较大
65
+ client_max_body_size 0;
66
+
67
+ location / {
68
+ proxy_pass http://LAN_IP:8082;
69
+ proxy_set_header Host $host;
70
+ proxy_set_header X-Real-IP $remote_addr;
71
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
72
+ proxy_set_header X-Forwarded-Proto $scheme;
73
+
74
+ # WebSocket 支持(实时日志、通知等)
75
+ proxy_http_version 1.1;
76
+ proxy_set_header Upgrade $http_upgrade;
77
+ proxy_set_header Connection "upgrade";
78
+
79
+ # 超时设置
80
+ proxy_connect_timeout 300;
81
+ proxy_send_timeout 300;
82
+ proxy_read_timeout 300;
83
+ }
84
+ }
package/dev/px-cli.md ADDED
@@ -0,0 +1,97 @@
1
+ # px-cli
2
+
3
+ Bun CLI project to interact with server using x-api-key method
4
+
5
+ ## Setup
6
+
7
+ ```bash
8
+ cd px
9
+ bun install
10
+ cp .env.example .env # fill in PX_BASE_URL, PX_API_KEY, PX_MERCHANT_UID
11
+ ```
12
+
13
+ ## Structure
14
+
15
+ ```
16
+ px/
17
+ ├── package.json # bun project, depends on @posx/core
18
+ ├── tsconfig.json
19
+ ├── .env.example
20
+ ├── index.ts # entry point & router (cac)
21
+ ├── http.ts # HTTP client with x-api-key auth
22
+ └── commands/
23
+ ├── category.ts # Category CRUD (types: ICategory)
24
+ └── product.ts # Product CRUD (types: IItem)
25
+ ```
26
+
27
+ ## Dependencies
28
+
29
+ - `@posx/core` — import types only (no service layer — no Dexie/IndexedDB in Bun):
30
+ - `IServiceOptions` — config typing in `http.ts`
31
+ - `ICategory` — category request/response typing
32
+ - `IItem` — product request/response typing
33
+ - `@litepos/autoquery` — `QueryBuilder` for `list` action (autoquery via `sapi` endpoint)
34
+ - `cac` — lightweight CLI framework (arg parsing, help text, subcommands)
35
+
36
+ ## Usage
37
+
38
+ ### Read (immediate)
39
+
40
+ ```bash
41
+ # List via autoquery (sapi)
42
+ px category list
43
+ px category list --nameContains Drinks --take 10
44
+ px product list
45
+ px product list --nameContains Latte --take 10
46
+
47
+ # Get by ID
48
+ px category get --id 123
49
+ px product get --id 456
50
+ ```
51
+
52
+ ### CUD — direct execution with dry-run
53
+
54
+ ```bash
55
+ # Add
56
+ px category add --name "Drinks" --type product --color "#ff0000" --icon "🍹"
57
+ px category add --name "Drinks" --dry-run # preview only
58
+
59
+ # Update (always fetches first: GET → show diff → PATCH)
60
+ px category update --id 123 --name "Beverages"
61
+ px product update --id 456 --price 6.00 --dry-run # preview diff
62
+
63
+ # Delete
64
+ px category delete --id 123
65
+ px product delete --id 456 --dry-run # preview record to be removed
66
+ ```
67
+
68
+ ### Update flow
69
+
70
+ ```
71
+ 1. GET /api/v5/merchants/{uid}/product/456
72
+ 2. Show diff:
73
+ - price: 5.00 → 6.00
74
+ 3. PATCH (or skip if --dry-run)
75
+ ```
76
+
77
+ `--dry-run` 和正常执行都会先 GET,区别只在是否发送 PATCH。
78
+
79
+ ## API
80
+
81
+ - **Base**: `https://lite-dev.posx.ai`
82
+ - **Auth**: `x-api-key` header
83
+
84
+ | Method | Route | Action |
85
+ |----------|-----------------------------------------------------|------------------|
86
+ | `GET` | `sapi/v5/merchants/{merchant_uid}/{module}` | list (autoquery) |
87
+ | `GET` | `api/v5/merchants/{merchant_uid}/{module}/{id}` | get |
88
+ | `PUT` | `api/v5/merchants/{merchant_uid}/{module}/{method}` | add |
89
+ | `PATCH` | `api/v5/merchants/{merchant_uid}/{module}/{id}` | update |
90
+ | `DELETE` | `api/v5/merchants/{merchant_uid}/{module}/{id}` | delete |
91
+
92
+ ## Ref
93
+
94
+ ```bash
95
+ curl -H "x-api-key: p8Hwl4A7ewynszODOOc05SJcqSP6YZDo2pevtZ" \
96
+ "https://lite-dev.posx.ai/api/v5/merchants/by-whatsapp-jid/6590992059@s.whatsapp.net"
97
+ ```
@@ -0,0 +1,5 @@
1
+ # 2026-02 测试日志
2
+
3
+ | # | 分支 | 时间 | 变更 | 测试 | 🌐 | 问题 | 状态 |
4
+ |---|------|------|------|------|:--:|------|------|
5
+ | 1 | bugfix/rounding-half-up-51 | 02-03 10:45 | roundingStep 实现 round half up | 19/20 passed | ✗ | `service-charge-and-tax-exempt.test.ts` 期望值需更新 5877→5876.9 | 🔧 需修复 |