From 2ff2ca768539ac9ea29179d09dfe74688807e3d5 Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Wed, 17 Jun 2026 18:59:51 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BE=9B=E5=BA=94=E5=95=86=E8=A1=A8?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=9C=BA=E6=9E=84ID=E3=80=81=E5=86=85?= =?UTF-8?q?=E5=A4=96=E9=83=A8=E6=A0=87=E8=AF=86=E3=80=81=E7=BB=93=E7=AE=97?= =?UTF-8?q?=E5=91=A8=E6=9C=9F/=E6=97=A5=E3=80=81=E4=BB=98=E6=AC=BE?= =?UTF-8?q?=E6=96=B9=E5=BC=8F=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - models/suppliers.json: 新增 orgid, is_external, settlement_cycle, settlement_day, payment_type - 外部供应商创建时自动在sage库开设机构 - 内部供应商通过机构名称搜索选择机构ID - suppliers_create.dspy: 处理is_external逻辑 - get_search_orgid.dspy: 机构名称搜索API - load_path.py: 注册新API路由 --- json/suppliers_list.json | 29 +++- models/suppliers.json | 43 ++++++ scripts/load_path.py | 1 + supplychain/init.py | 38 ++++- wwwroot/api/get_search_orgid.dspy | 15 ++ wwwroot/api/suppliers_create.dspy | 28 ++++ wwwroot/suppliers_list/get_suppliers.dspy | 37 ++++- wwwroot/suppliers_list/index.ui | 173 +++++++++++++++++++++- 8 files changed, 354 insertions(+), 10 deletions(-) create mode 100644 wwwroot/api/get_search_orgid.dspy diff --git a/json/suppliers_list.json b/json/suppliers_list.json index 03c31bc..7c3a6c7 100644 --- a/json/suppliers_list.json +++ b/json/suppliers_list.json @@ -8,17 +8,42 @@ "data_filter": { "AND": [ {"field": "supplier_name", "op": "LIKE", "var": "supplier_name"}, + {"field": "is_external", "op": "=", "var": "is_external"}, {"field": "status", "op": "=", "var": "status"} ] }, "filter_labels": { "supplier_name": "供应商名称", + "is_external": "供应商类型", "status": "状态" }, - "editexclouded": ["id", "resellerid", "created_by", "created_at", "updated_at"], + "editexclouded": ["id", "resellerid", "status", "created_by", "created_at", "updated_at"], "browserfields": { - "exclouded": ["id", "resellerid" ], + "exclouded": ["id", "resellerid", "created_by"], "alters": { + "is_external": { + "uitype": "code", + "data": [ + {"value": "1", "text": "外部供应商"}, + {"value": "0", "text": "内部供应商"} + ] + }, + "payment_type": { + "uitype": "code", + "data": [ + {"value": "prepaid", "text": "预付费"}, + {"value": "postpaid", "text": "后付费"} + ] + }, + "settlement_cycle": { + "uitype": "code", + "data": [ + {"value": "monthly", "text": "月结"}, + {"value": "weekly", "text": "周结"}, + {"value": "biweekly", "text": "半月结"}, + {"value": "quarterly", "text": "季结"} + ] + }, "status": { "uitype": "code", "data": [ diff --git a/models/suppliers.json b/models/suppliers.json index 22fd11a..78c2860 100644 --- a/models/suppliers.json +++ b/models/suppliers.json @@ -78,6 +78,38 @@ "type": "str", "length": 64 }, + { + "name": "orgid", + "title": "机构ID", + "type": "str", + "length": 32, + "nullable": "no" + }, + { + "name": "is_external", + "title": "是否外部供应商", + "type": "char", + "length": 1, + "nullable": "no", + "default": "1" + }, + { + "name": "settlement_cycle", + "title": "结算周期", + "type": "str", + "length": 20 + }, + { + "name": "settlement_day", + "title": "结算日", + "type": "int" + }, + { + "name": "payment_type", + "title": "付款方式", + "type": "str", + "length": 20 + }, { "name": "status", "title": "状态", @@ -115,6 +147,11 @@ "idxtype": "index", "idxfields": ["resellerid"] }, + { + "name": "idx_suppliers_orgid", + "idxtype": "index", + "idxfields": ["orgid"] + }, { "name": "idx_suppliers_code", "idxtype": "unique", @@ -127,6 +164,12 @@ "table": "organization", "valuefield": "id", "textfield": "orgname" + }, + { + "field": "orgid", + "table": "organization", + "valuefield": "id", + "textfield": "orgname" } ] } diff --git a/scripts/load_path.py b/scripts/load_path.py index d169d4e..363605d 100755 --- a/scripts/load_path.py +++ b/scripts/load_path.py @@ -101,6 +101,7 @@ PATHS_LOGINED = [ "/supplychain/api/get_search_productid.dspy", "/supplychain/api/get_search_sub_reseller_id.dspy", "/supplychain/api/get_search_agreement_id.dspy", + "/supplychain/api/get_search_orgid.dspy", # CRUD API — sub_distributors "/supplychain/api/sub_distributors_create.dspy", "/supplychain/api/sub_distributors_update.dspy", diff --git a/supplychain/init.py b/supplychain/init.py index 0d90e2c..ce9e02b 100644 --- a/supplychain/init.py +++ b/supplychain/init.py @@ -95,6 +95,35 @@ async def create_supplier(request, params_kw): resellerid = await env.get_userorgid() data = params_kw db, dbname = _get_sor() + + # Handle external supplier: create new org + is_external = data.get("is_external", "1") + orgid = data.get("orgid") + + if is_external == "1" and not orgid: + # External supplier: create new organization + supplier_name = data.get("supplier_name") + if not supplier_name: + return json.dumps({"status": "error", "message": "供应商名称不能为空"}) + + # Create org in sage database + new_orgid = getID() + now_org = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + org_rec = { + "id": new_orgid, + "orgname": supplier_name, + "orgtype": "supplier", + "status": "1", + "created_by": user_id, + "created_at": now_org, + "updated_at": now_org + } + async with db.sqlorContext("sage") as sor_sage: + await sor_sage.C("organization", org_rec) + orgid = new_orgid + elif is_external == "0" and not orgid: + return json.dumps({"status": "error", "message": "内部供应商必须选择所属机构"}) + async with db.sqlorContext(dbname) as sor: supplier_code = data.get("supplier_code") or _generate_supplier_code(resellerid) now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") @@ -110,6 +139,11 @@ async def create_supplier(request, params_kw): "tax_number": data.get("tax_number"), "bank_name": data.get("bank_name"), "bank_account": data.get("bank_account"), + "orgid": orgid, + "is_external": is_external, + "settlement_cycle": data.get("settlement_cycle"), + "settlement_day": data.get("settlement_day"), + "payment_type": data.get("payment_type"), "status": data.get("status", "1"), "remark": data.get("remark"), "created_by": user_id, @@ -128,7 +162,9 @@ async def update_supplier(request, params_kw): now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") rec = {"id": data["id"], "updated_at": now} for key in ["supplier_name", "contact_person", "contact_phone", "contact_email", - "address", "tax_number", "bank_name", "bank_account", "status", "remark"]: + "address", "tax_number", "bank_name", "bank_account", + "orgid", "is_external", "settlement_cycle", "settlement_day", + "payment_type", "status", "remark"]: if key in data: rec[key] = data[key] await sor.U("suppliers", rec) diff --git a/wwwroot/api/get_search_orgid.dspy b/wwwroot/api/get_search_orgid.dspy new file mode 100644 index 0000000..b543fc4 --- /dev/null +++ b/wwwroot/api/get_search_orgid.dspy @@ -0,0 +1,15 @@ +result = [{'orgid': '', 'orgid_text': '全部'}] +try: + userorgid = await get_userorgid() + if not userorgid: + return json.dumps(result, ensure_ascii=False) + db = DBPools() + async with db.sqlorContext('sage') as sor: + rows = await sor.sqlExe( + "select id as orgid, orgname as orgid_text from organization where status = '1' order by orgname", + {} + ) + return json.dumps(result + list(rows), ensure_ascii=False) +except Exception as e: + debug(f'get_search_orgid error: {e}') +return json.dumps(result, ensure_ascii=False) diff --git a/wwwroot/api/suppliers_create.dspy b/wwwroot/api/suppliers_create.dspy index c558f81..a4485c2 100644 --- a/wwwroot/api/suppliers_create.dspy +++ b/wwwroot/api/suppliers_create.dspy @@ -12,6 +12,34 @@ try: data['created_at'] = timestampstr() data['updated_at'] = timestampstr() + # Handle external supplier: create new org + is_external = data.get('is_external', '1') + orgid = data.get('orgid') + + if is_external == '1' and not orgid: + supplier_name = data.get('supplier_name') + if not supplier_name: + result['options'] = {'title': 'Error', 'message': '供应商名称不能为空', 'type': 'error'} + return json.dumps(result, ensure_ascii=False) + new_orgid = getID() + now_org = timestampstr() + org_rec = { + 'id': new_orgid, + 'orgname': supplier_name, + 'orgtype': 'supplier', + 'status': '1', + 'created_by': user_id, + 'created_at': now_org, + 'updated_at': now_org + } + db = DBPools() + async with db.sqlorContext('sage') as sor_sage: + await sor_sage.C('organization', org_rec) + data['orgid'] = new_orgid + elif is_external == '0' and not orgid: + result['options'] = {'title': 'Error', 'message': '内部供应商必须选择所属机构', 'type': 'error'} + return json.dumps(result, ensure_ascii=False) + async with DBPools().sqlorContext(dbname) as sor: await sor.C('suppliers', data) diff --git a/wwwroot/suppliers_list/get_suppliers.dspy b/wwwroot/suppliers_list/get_suppliers.dspy index 2a3b3c6..6a3803b 100644 --- a/wwwroot/suppliers_list/get_suppliers.dspy +++ b/wwwroot/suppliers_list/get_suppliers.dspy @@ -27,9 +27,10 @@ if not ns.get('sort'): -sql = '''select a.*, b.resellerid_text +sql = '''select a.*, b.resellerid_text, c.orgid_text from (select * from suppliers where 1=1 [[filterstr]]) a left join (select id as resellerid, - orgname as resellerid_text from organization where 1 = 1) b on a.resellerid = b.resellerid''' + orgname as resellerid_text from organization where 1 = 1) b on a.resellerid = b.resellerid left join (select id as orgid, + orgname as orgid_text from organization where 1 = 1) c on a.orgid = c.orgid''' filterjson = params_kw.get('data_filter') if filterjson and isinstance(filterjson, str): @@ -108,6 +109,38 @@ fields_str=r'''[ "type": "str", "length": 64 }, + { + "name": "orgid", + "title": "机构ID", + "type": "str", + "length": 32, + "nullable": "no" + }, + { + "name": "is_external", + "title": "是否外部供应商", + "type": "char", + "length": 1, + "nullable": "no", + "default": "1" + }, + { + "name": "settlement_cycle", + "title": "结算周期", + "type": "str", + "length": 20 + }, + { + "name": "settlement_day", + "title": "结算日", + "type": "int" + }, + { + "name": "payment_type", + "title": "付款方式", + "type": "str", + "length": 20 + }, { "name": "status", "title": "状态", diff --git a/wwwroot/suppliers_list/index.ui b/wwwroot/suppliers_list/index.ui index ab7cbd4..07eb52d 100644 --- a/wwwroot/suppliers_list/index.ui +++ b/wwwroot/suppliers_list/index.ui @@ -20,13 +20,13 @@ "editable":{ - "new_data_url":"{{entire_url('add_suppliers.dspy')}}", + "new_data_url":"{{entire_url('../api/suppliers_create.dspy')}}", - "delete_data_url":"{{entire_url('delete_suppliers.dspy')}}", + "delete_data_url":"{{entire_url('../api/suppliers_delete.dspy')}}", - "update_data_url":"{{entire_url('update_suppliers.dspy')}}" + "update_data_url":"{{entire_url('../api/suppliers_update.dspy')}}" }, @@ -41,9 +41,58 @@ "browserfields": { "exclouded": [ - "id" + "id", + "resellerid", + "created_by" ], "alters": { + "is_external": { + "uitype": "code", + "data": [ + { + "value": "1", + "text": "外部供应商" + }, + { + "value": "0", + "text": "内部供应商" + } + ] + }, + "payment_type": { + "uitype": "code", + "data": [ + { + "value": "prepaid", + "text": "预付费" + }, + { + "value": "postpaid", + "text": "后付费" + } + ] + }, + "settlement_cycle": { + "uitype": "code", + "data": [ + { + "value": "monthly", + "text": "月结" + }, + { + "value": "weekly", + "text": "周结" + }, + { + "value": "biweekly", + "text": "半月结" + }, + { + "value": "quarterly", + "text": "季结" + } + ] + }, "status": { "uitype": "code", "data": [ @@ -61,6 +110,15 @@ }, + "editexclouded":[ + "id", + "resellerid", + "status", + "created_by", + "created_at", + "updated_at" +], + "fields":[ { "name": "id", @@ -84,7 +142,7 @@ "valueField": "resellerid", "textField": "resellerid_text", "params": { - "dbname": "{{get_module_dbname('supplychain')}}", + "dbname": "sage", "table": "organization", "tblvalue": "id", "tbltext": "orgname", @@ -185,6 +243,105 @@ "datatype": "str", "label": "银行账号" }, + { + "name": "orgid", + "title": "机构ID", + "type": "str", + "length": 32, + "nullable": "no", + "label": "机构ID", + "uitype": "code", + "valueField": "orgid", + "textField": "orgid_text", + "params": { + "dbname": "sage", + "table": "organization", + "tblvalue": "id", + "tbltext": "orgname", + "valueField": "orgid", + "textField": "orgid_text" + }, + "dataurl": "{{entire_url('/appbase/get_code.dspy')}}" + }, + { + "name": "is_external", + "title": "是否外部供应商", + "type": "char", + "length": 1, + "nullable": "no", + "default": "1", + "cwidth": 4, + "uitype": "code", + "datatype": "char", + "label": "是否外部供应商", + "data": [ + { + "value": "1", + "text": "外部供应商" + }, + { + "value": "0", + "text": "内部供应商" + } + ] + }, + { + "name": "settlement_cycle", + "title": "结算周期", + "type": "str", + "length": 20, + "cwidth": 18, + "uitype": "code", + "datatype": "str", + "label": "结算周期", + "data": [ + { + "value": "monthly", + "text": "月结" + }, + { + "value": "weekly", + "text": "周结" + }, + { + "value": "biweekly", + "text": "半月结" + }, + { + "value": "quarterly", + "text": "季结" + } + ] + }, + { + "name": "settlement_day", + "title": "结算日", + "type": "int", + "length": 0, + "uitype": "int", + "datatype": "int", + "label": "结算日" + }, + { + "name": "payment_type", + "title": "付款方式", + "type": "str", + "length": 20, + "cwidth": 18, + "uitype": "code", + "datatype": "str", + "label": "付款方式", + "data": [ + { + "value": "prepaid", + "text": "预付费" + }, + { + "value": "postpaid", + "text": "后付费" + } + ] + }, { "name": "status", "title": "状态", @@ -257,6 +414,11 @@ "op": "LIKE", "var": "supplier_name" }, + { + "field": "is_external", + "op": "=", + "var": "is_external" + }, { "field": "status", "op": "=", @@ -268,6 +430,7 @@ "filter_labels":{ "supplier_name": "供应商名称", + "is_external": "供应商类型", "status": "状态" },