139 Commits

Author SHA1 Message Date
ad86b87f4f docs(README): 补provider_recharge.ui条目与主题约定(不硬编码暗色,跟随宿主双主题) 2026-09-08 15:56:46 +08:00
a34407816c fix(主题): 供应商充值页去硬编码暗色——标题/汇总条/表单容器改css:card与继承色,Tabular去bgcolor覆盖,跟随pipeline-app的data-theme暗亮双主题 2026-09-08 15:48:22 +08:00
ymq
aa2c1604d1 fix(suppliers): 库名写死 sage 改 get_module_dbname 跨应用解析
单库应用(如 pipeline)get_module_dbname 全返回主库,写死 'sage' 会把供应商
机构写到错库。开户旁路化:失败不阻断供应商创建。
2026-08-26 18:10:35 +08:00
ymq
927ee954ac fix(calculate_sale_amounts): SQL 补「产品精确+类别默认」匹配分支
原 SQL 只覆盖: (类别+产品精确)/(类别精确+产品默认)/(全默认),
缺「产品精确+类别为NULL」,导致只填 productid 不填 prodtypeid 的折扣查不到,
supply_discount 回落到 default_discount=1.0。补第3优先级。
2026-08-26 16:54:55 +08:00
ymq
3a93804655 perf(load_path): 批量直写 DB,避免 159 次 subprocess 启动
原 subprocess.run(set_role_perm.py) 每个路径起一个 python 进程,159 路径太慢。
改为一次连接批量注册 permission + rolepermission。
2026-08-26 16:42:51 +08:00
ymq
ebff8d7f08 fix(models): sub_distributors created_at/updated_at 去掉带引号的 CURRENT_TIMESTAMP default
default: "CURRENT_TIMESTAMP" 让 json2ddl 生成 DEFAULT 'CURRENT_TIMESTAMP'(带引号),
MySQL 报 Invalid default value for created_at,导致建表中断(11张表未建)。
2026-08-26 16:41:48 +08:00
ymq
2bc6288fae feat(pipeline): 适配 pipeline 部署
- scripts/load_path.py: Sage 格式(硬编码 sage 库+旧 permission 表) → pipeline 格式(set_role_perm.py)
  159 路径(any=1 logined=158)
- init.py: 2 处 db.sqlorContext('sage') 直接连库名 → db.sqlorContext(dbname) 动态映射
  (pipeline 单库,organization/product 都在 pipeline 库;get_sor_context/get_module_dbname
  已走映射无需改)
2026-08-26 16:40:14 +08:00
bfd691f9ac sub_distributors添加sub_distributorid(org_id)字段+唯一索引,对齐sub_resellers 2026-07-20 20:13:52 +08:00
8bb688374c fix: 移除误提交的supplychain/__pycache__中间文件(.gitignore已有规则) 2026-07-20 16:39:48 +08:00
a6eca85d7f 删除未使用的 _generate_sub_reseller_code 函数,清理 sub_reseller_code 残留 2026-07-20 15:31:32 +08:00
1303b48685 fix: sub_reseller_code → sub_resellerid (存org_id,修复多层分销链遍历)
- sub_resellers.json 模型: sub_reseller_code(varchar 64) → sub_resellerid(varchar 32)
- 唯一索引: idx_sr_code → idx_sr_sub_resellerid
- codes 关联: sub_resellerid 关联 organization.orgname
- init.py create_sub_reseller: 写入 sub_resellers 表(非 sub_distributors),字段 sub_resellerid
- init.py get_distribution_chain: SQL SELECT sub_resellerid(非 orgid)
- JSON/UI/dspy 字段引用同步更新
- DDL 重新生成
2026-07-20 15:25:38 +08:00
e6d5998c15 fix: use ServerEnv().get_module_dbname('sage') instead of hardcoded 'sage' 2026-07-15 14:02:26 +08:00
a42d362995 chore: untrack CRUD intermediate files (already in .gitignore) 2026-07-14 18:03:46 +08:00
b3c61a6758 fix: p.name→p.product_name; remove spurious COLLATE in JOIN 2026-07-14 16:07:25 +08:00
9cd393c3b2 fix: 合同附件上传后列表不刷新、消息不显示的bug
- 上传后: old_params=null 破环再 render({}) 强制刷新列表
- 上传/删除后: 解析 JSON 响应并用 bricks.widgetBuild() 显示消息
- 删除后同样破环强制刷新
- URL 参数用 encodeURIComponent 防特殊字符问题
- 下载增加无路径时的兜底提示
2026-07-14 12:54:49 +08:00
14d03375b2 feat: 供销合同和分销协议补回附件管理功能
- xls2ui 重新生成 index.ui,包含合同附件 toolbar 按钮和 popup bind
- 添加 contract_attach.svg 图标
- 更新 CRUD dspy 文件
2026-07-14 12:06:49 +08:00
bc46774401 refactor: 取消内部供应商概念,统一为外部; 修复ServerEnv→request._run_ns; 修复editable嵌套 2026-07-13 17:06:57 +08:00
44042b80dd fix: 供销协议折扣明细直接用product.providerid过滤
product.providerid已直接存储供应商ID,不再需要JOIN product_resource_supplier
2026-07-13 14:58:50 +08:00
f5794c9348 fix: 供销协议折扣明细按资源供应方过滤产品
正确链路: product.resource_ref_id → product_resource_supplier.supplier_org_id
JOIN product_resource_supplier 按 supplier_org_id 过滤,而非 product_supplier_mapping
2026-07-13 14:34:52 +08:00
dbf6946b16 fix: 供销协议折扣明细通过product_supplier_mapping关联产品
产品与供应商的关联在product_supplier_mapping表(supplier_org_id/external_supplier_id),
不在product.org_id。修复后:
1. 查合同→供应商→supplier_orgid+supplier_id
2. 查product_supplier_mapping获取该供应商的产品ID列表
3. 用产品ID列表过滤product表
2026-07-13 14:22:23 +08:00
de10fb00f3 fix: 供销协议折扣明细按供应商org过滤产品
- get_contract_discount_items: 改为根据合同的supplier_id查询供应商的orgid,
  用供应商orgid过滤产品列表,而非用当前用户orgid过滤
- get_agreement_discount_items: ServerEnv()裸单例→request._run_ns.get_userorgid()
  解决env.orgid永远为None导致回退到'0'的问题
2026-07-13 11:19:41 +08:00
e7a4535423 fix: add_sub_distributor_admin - 用orgtypeid+name查role, 补parentid+org_type 2026-07-13 11:14:02 +08:00
9afb3c279b fix: save dspys return Message widget for visual feedback
script actiontype forbidden in bricks; use Message widget instead.
Status column reflects saved state on page load/reload.
2026-07-12 23:25:22 +08:00
e2811156b0 fix: add id to status widgets + return item_id from save dspys 2026-07-12 23:23:34 +08:00
5a00a42f05 fix: check product_org_auth exists before insert in save_agreement_discount 2026-07-12 23:19:42 +08:00
41ccfcb301 fix: use get_sor_context(env, dbname) — correct sqlor pattern for module Python
env = request._run_ns; get_sor_context(env, 'sage') for products
get_sor_context(env, 'supplychain') for agreement/contract items
2026-07-12 23:05:24 +08:00
49b6cbe85b fix: use _get_sor() instead of get_module_dbname() in discount item queries 2026-07-12 23:01:44 +08:00
8fde34ee8d fix: split discount item queries across sage + supplychain DBs
Can't cross-db JOIN — sage user lacks supplychain table access.
Query products from sage, items from supplychain, merge in Python.
2026-07-12 22:58:46 +08:00
14c8f2fbd3 fix: get_*_discount_items accept only request (Jinja2 call pattern)
Jinja2 templates call ServerEnv functions with (request) not (request, params_kw).
params_kw extracted from request._run_ns.params_kw instead.
2026-07-12 22:56:06 +08:00
0107eebdcb feat: discount setting UI for agreement/contract items (like discount module pattern)
- agreement_discount_setting.ui: product list with UiFloat discount inputs
- contract_discount_setting.ui: same for supply contracts
- get_agreement_discount_items.dspy + Python function
- get_contract_discount_items.dspy + Python function
- save_agreement_discount.dspy: create/update/delete items on discount change
- save_contract_discount.dspy: same for supply contracts
- Updated distribution_agreements_list and supply_contracts_list subtables
2026-07-12 10:51:18 +08:00
85ae9802a2 fix: add agreement_id/contract_id to editexclouded in items CRUD
Fields auto-set from parent context, no need for user input.
2026-07-12 10:39:21 +08:00
2f2c9c42e7 fix: remove cheight from items_list CRUD index.ui 2026-07-12 10:36:58 +08:00
b69bd38b27 fix: toolbar buttons open CRUD page directly, remove ensure dspy layer
Suppliers '供销协议' → /supplychain/supply_contracts_list?supplier_id=
Sub-distributors '分销协议' → /supplychain/distribution_agreements_list?sub_reseller_id=

No more DataViewer/HTML-redirect popup issues.
2026-07-12 10:32:45 +08:00
1e7f713725 fix: use HTML meta refresh redirect instead of DataViewer or 302
PopupWindow renders dspy response directly. DataViewer doesn't
work inside popup context. HTML meta refresh redirects to CRUD page.
2026-07-12 10:28:24 +08:00
a930847317 fix: ensure dspy returns 302 redirect instead of DataViewer widget
PopupWindow can't render DataViewer returned from dspy.
Now dspy creates contract/agreement if needed, then 302→CRUD page.
2026-07-12 10:27:27 +08:00
a3176e4f34 fix: use absolute /supplychain/ URLs in JSON CRUD source configs
Same as index.ui fix — entire_url() relative paths lose module prefix.
Now both generated files AND source configs use absolute paths.
2026-07-12 10:19:30 +08:00
7f2c265764 fix: use absolute /supplychain/ URLs in all CRUD-generated index.ui
entire_url() relative paths resolve without module prefix
in bricks DataViewer context. Changed all to /supplychain/... paths.
2026-07-12 10:18:25 +08:00
3159afbede fix: get_search_prodtypeid/productid query correct DB (sage) and tables
- prodtypeid: product_types→product_category, supplychain→sage
- productid: products→product, supplychain→sage
2026-07-12 09:37:38 +08:00
0049db58e5 fix: move product_org_auth sync to distribution_agreement_items (not supply_contract_items)
- supply_contract_items: revert — products already belong to reseller's own org
- distribution_agreement_items: create → insert product_org_auth for sub_reseller
- distribution_agreement_items: delete → remove product_org_auth
- org_id in product_org_auth = sub_reseller_id (二级分销商)
2026-07-10 15:48:27 +08:00
3c98e8a991 feat: sync product_org_auth on supply_contract_items create/delete 2026-07-10 15:38:28 +08:00
49d59c3ed0 fix: auto-set managed_by to current user when creating sub_distributor 2026-07-10 14:14:09 +08:00
fac526637b fix: add id to userrole insert + remove manual created_at (DB has defaults) 2026-07-10 14:01:05 +08:00
fb579cbd2f fix: use sor.R for role lookup + proper datetime format
- Changed raw SQL role query to sor.R('role', {'role': name})
- Fixed timestampstr() → datetime format to avoid data truncation
- Added logined + reseller.operator roles alongside admin
2026-07-10 13:52:14 +08:00
ed4898bf90 fix: use absolute /supplychain/ paths in ensure dspy DataViewer URLs
Relative ../ paths inside PopupWindow DataViewer resolve without
module prefix. Use absolute /supplychain/ paths instead.
2026-07-10 13:51:06 +08:00
916b501c67 feat: add admin + reset admin password toolbar for sub_distributors
- api/add_sub_distributor_admin.dspy: create org+user+reseller.admin role, show password
- api/reset_sub_distributor_admin_pwd.dspy: reset admin password, show new password
- sub_distributors_list: add toolbar buttons with popup binds
2026-07-10 12:15:31 +08:00
efe45215f0 fix: add /supplychain/ prefix to entire_url in index.ui and menu.ui
entire_url() without module prefix resolves to wrong path,
causing 403 on RBAC check. Now uses absolute /supplychain/ paths.
2026-07-10 11:59:08 +08:00
749047814f fix: use DataViewer instead of UrlWidget (UrlWidget ignores w/h; DataViewer works) 2026-07-10 11:30:05 +08:00
e0dc9963b7 feat: sub_distributors_create now creates organization + supply relation 2026-07-10 11:16:30 +08:00
0c718cf461 fix: fix column name + ensure dspy now returns CRUD page after create
- sub_resellers column is sub_reseller_name (not sub_dist_name)
- After ensure, return UrlWidget loading CRUD list filtered by id
- Popup size increased for CRUD page viewing
2026-07-10 11:11:21 +08:00
7fa70b9a24 fix: use urlwidget+PopupWindow instead of script/dspy for toolbar binds
bricks.js only supports 5 actiontypes; dspy and script with fetch
are not available. Use urlwidget with PopupWindow target instead.
2026-07-10 11:03:56 +08:00