diff --git a/json/distribution_agreements_list.json b/json/distribution_agreements_list.json index 84f30b4..b55d2f7 100644 --- a/json/distribution_agreements_list.json +++ b/json/distribution_agreements_list.json @@ -83,6 +83,15 @@ "title": "产品分销折扣", "url": "{{entire_url('../distribution_agreement_items_list')}}", "subtable": "distribution_agreement_items" + }, + { + "field": "contract_id", + "title": "合同附件", + "url": "{{entire_url('../api/contract_attach.ui')}}?contract_type=distribution", + "subtable": "contract_attach", + "mapping": { + "contract_id": "id" + } } ], "editable": { diff --git a/json/supply_contracts_list.json b/json/supply_contracts_list.json index 8d7935e..a78caf1 100644 --- a/json/supply_contracts_list.json +++ b/json/supply_contracts_list.json @@ -88,6 +88,15 @@ "title": "产品折扣明细", "url": "{{entire_url('../supply_contract_items_list')}}", "subtable": "supply_contract_items" + }, + { + "field": "contract_id", + "title": "合同附件", + "url": "{{entire_url('../api/contract_attach.ui')}}?contract_type=supply", + "subtable": "contract_attach", + "mapping": { + "contract_id": "id" + } } ] } diff --git a/supplychain/init.py b/supplychain/init.py index ce9e02b..11e2a6f 100644 --- a/supplychain/init.py +++ b/supplychain/init.py @@ -924,4 +924,26 @@ def load_supplychain(): env.delete_product_supplier_mapping = delete_product_supplier_mapping # Calculation API env.calculate_sale_amounts = calculate_sale_amounts + # Attachment folder helper + env.ensure_contract_folder = ensure_contract_folder return True + + +async def ensure_contract_folder(request, contract_id, fiid): + """Ensure a filemgr folder exists for a contract attachment. + Returns the folderid (uses contract_id as folder id).""" + db, dbname = _get_sor() + async with db.sqlorContext(dbname) as sor: + recs = await sor.sqlExe( + "SELECT id FROM folder WHERE fiid=${fiid}$ AND name=${name}$", + {'fiid': fiid, 'name': contract_id} + ) + if recs and len(recs) > 0: + return recs[0].id + # Create new folder + fid = getID() + await sor.sqlExe( + "INSERT INTO folder (id, parentid, fiid, name, ownerid) VALUES (${id}$, ${pid}$, ${fiid}$, ${name}$, ${oid}$)", + {'id': fid, 'pid': '0', 'fiid': fiid, 'name': contract_id, 'oid': '0'} + ) + return fid diff --git a/wwwroot/api/contract_attach.ui b/wwwroot/api/contract_attach.ui new file mode 100644 index 0000000..be8a27d --- /dev/null +++ b/wwwroot/api/contract_attach.ui @@ -0,0 +1,83 @@ +{% set contract_id = params_kw.get('contract_id', '') %} +{% set contract_type = params_kw.get('contract_type', 'supply') %} +{% if contract_type == 'supply' %} +{% set fiid = 'supply_contract_attach' %} +{% else %} +{% set fiid = 'dist_agreement_attach' %} +{% endif %} +{% set folder = ensure_contract_folder(request, contract_id, fiid) %} +{ + "widgettype": "VBox", + "options": { + "width": "100%", + "padding": "8px" + }, + "subwidgets": [ + { + "widgettype": "HBox", + "options": { + "alignItems": "center", + "marginBottom": "12px" + }, + "subwidgets": [ + { + "widgettype": "Title4", + "options": { + "fontWeight": "600", + "otext": "合同附件", + "i18n": true + } + }, + { + "widgettype": "Filler" + }, + { + "widgettype": "Button", + "options": { + "label": "上传附件", + "css": "primary", + "borderRadius": "6px", + "padding": "4px 12px" + }, + "binds": [{ + "wid": "self", + "event": "click", + "actiontype": "urlwidget", + "target": "PopupWindow", + "popup_options": { + "title": "上传附件", + "width": "450px", + "height": "200px", + "dismiss_events": ["cancel"] + }, + "options": { + "url": "{{entire_url('/filemgr/upload_file.ui')}}?id={{folder}}&fiid={{fiid}}" + } + }] + } + ] + }, + { + "widgettype": "Tabular", + "options": { + "css": "card", + "width": "100%", + "height": "auto", + "data_url": "{{entire_url('contract_attach_list.dspy')}}?folderid={{folder}}&fiid={{fiid}}", + "data_method": "GET", + "page_rows": 50, + "row_options": { + "browserfields": { + "exclouded": [], + "cwidth": {} + }, + "fields": [ + {"name": "filename", "title": "文件名", "type": "str", "uitype": "str", "label": "文件名", "cwidth": 30}, + {"name": "filesize", "title": "大小(bytes)", "type": "int", "uitype": "int", "label": "大小", "cwidth": 10}, + {"name": "filetype", "title": "类型", "type": "str", "uitype": "str", "label": "类型", "cwidth": 8} + ] + } + } + } + ] +} diff --git a/wwwroot/api/contract_attach_list.dspy b/wwwroot/api/contract_attach_list.dspy new file mode 100644 index 0000000..4bf175c --- /dev/null +++ b/wwwroot/api/contract_attach_list.dspy @@ -0,0 +1,29 @@ +# coding=utf-8 +"""获取合同附件文件列表。 +输入: folderid, fiid +输出: {rows: [{id, filename, filesize, filetype, webpath}]} +""" +folderid = params_kw.get('folderid', '') +fiid = params_kw.get('fiid', '') + +if not folderid: + return json.dumps({'total': 0, 'rows': []}) + +dbname = get_module_dbname('supplychain') +db = DBPools() + +async with db.sqlorContext(dbname) as sor: + recs = await sor.sqlExe( + "SELECT id, name, filesize, filetype, webpath FROM file WHERE folderid=${folderid}$ AND fiid=${fiid}$ ORDER BY id", + {'folderid': folderid, 'fiid': fiid} + ) + rows = [] + for r in recs: + rows.append({ + 'id': r.id, + 'filename': r.name, + 'filesize': r.filesize or 0, + 'filetype': r.filetype or '', + 'webpath': r.webpath or '' + }) + return json.dumps({'total': len(rows), 'rows': rows})