Compare commits
No commits in common. "092d74133e77ce2ae365361d421417b031fe0cd4" and "4c1efe56a87d7da5ff3150f58ee93e99da1bb378" have entirely different histories.
092d74133e
...
4c1efe56a8
51
build.sh
51
build.sh
@ -1,51 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -e
|
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
||||||
cd "$SCRIPT_DIR"
|
|
||||||
|
|
||||||
# Find Sage root directory
|
|
||||||
SAGE_ROOT=""
|
|
||||||
for candidate in "$SCRIPT_DIR/../.." "$HOME/repos/sage" "$HOME/sage"; do
|
|
||||||
if [ -d "$candidate/wwwroot" ] && [ -d "$candidate/py3/bin" ]; then
|
|
||||||
SAGE_ROOT="$(cd "$candidate" && pwd)"
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ -z "$SAGE_ROOT" ]; then
|
|
||||||
echo "ERROR: Cannot find Sage root directory"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Sage root: $SAGE_ROOT"
|
|
||||||
|
|
||||||
# Install module
|
|
||||||
cd "$SCRIPT_DIR"
|
|
||||||
$SAGE_ROOT/py3/bin/pip install -e .
|
|
||||||
|
|
||||||
# Generate DDL from models
|
|
||||||
if [ -d "$SCRIPT_DIR/models" ]; then
|
|
||||||
echo "Generating DDL..."
|
|
||||||
cd "$SCRIPT_DIR/models"
|
|
||||||
$SAGE_ROOT/py3/bin/json2ddl mysql . > mysql.ddl.sql
|
|
||||||
echo "DDL generated: $SCRIPT_DIR/models/mysql.ddl.sql"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Generate CRUD UI from json definitions
|
|
||||||
if [ -d "$SCRIPT_DIR/json" ]; then
|
|
||||||
echo "Generating CRUD UI files..."
|
|
||||||
cd "$SCRIPT_DIR/json"
|
|
||||||
for f in *.json; do
|
|
||||||
echo " Processing $f..."
|
|
||||||
done
|
|
||||||
$SAGE_ROOT/py3/bin/xls2ui -m ../models -o ../wwwroot supplychain *.json
|
|
||||||
echo "CRUD UI files generated."
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create symlink in Sage wwwroot
|
|
||||||
echo "Creating wwwroot symlink..."
|
|
||||||
rm -f "$SAGE_ROOT/wwwroot/supplychain"
|
|
||||||
ln -s "$SCRIPT_DIR/wwwroot" "$SAGE_ROOT/wwwroot/supplychain"
|
|
||||||
|
|
||||||
echo "Build complete."
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{}
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
{
|
|
||||||
"tblname": "distribution_agreement_items",
|
|
||||||
"alias": "distribution_agreement_items_list",
|
|
||||||
"title": "分销协议产品折扣",
|
|
||||||
"params": {
|
|
||||||
"sortby": [
|
|
||||||
"created_at desc"
|
|
||||||
],
|
|
||||||
"logined_userorgid": "resellerid",
|
|
||||||
"browserfields": {
|
|
||||||
"exclouded": [
|
|
||||||
"created_at"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"editexclouded": [
|
|
||||||
"id",
|
|
||||||
"resellerid",
|
|
||||||
"agreement_id",
|
|
||||||
"created_at"
|
|
||||||
],
|
|
||||||
"editable": {
|
|
||||||
"new_data_url": "{{entire_url('../api/distribution_agreement_items_create.dspy')}}",
|
|
||||||
"update_data_url": "{{entire_url('../api/distribution_agreement_items_update.dspy')}}",
|
|
||||||
"delete_data_url": "{{entire_url('../api/distribution_agreement_items_delete.dspy')}}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,57 +0,0 @@
|
|||||||
{
|
|
||||||
"tblname": "distribution_agreements",
|
|
||||||
"alias": "distribution_agreements_list",
|
|
||||||
"title": "分销协议管理",
|
|
||||||
"params": {
|
|
||||||
"sortby": [
|
|
||||||
"created_at desc"
|
|
||||||
],
|
|
||||||
"logined_userorgid": "resellerid",
|
|
||||||
"browserfields": {
|
|
||||||
"exclouded": [
|
|
||||||
"created_by",
|
|
||||||
"created_at",
|
|
||||||
"updated_at"
|
|
||||||
],
|
|
||||||
"alters": {
|
|
||||||
"status": {
|
|
||||||
"uitype": "code",
|
|
||||||
"data": [
|
|
||||||
{
|
|
||||||
"value": "1",
|
|
||||||
"text": "有效"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"value": "0",
|
|
||||||
"text": "无效"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"value": "2",
|
|
||||||
"text": "已过期"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"editexclouded": [
|
|
||||||
"id",
|
|
||||||
"resellerid",
|
|
||||||
"created_by",
|
|
||||||
"created_at",
|
|
||||||
"updated_at"
|
|
||||||
],
|
|
||||||
"subtables": [
|
|
||||||
{
|
|
||||||
"field": "id",
|
|
||||||
"title": "产品折扣",
|
|
||||||
"url": "{{entire_url('../distribution_agreement_items_list')}}",
|
|
||||||
"subtable": "distribution_agreement_items"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"editable": {
|
|
||||||
"new_data_url": "{{entire_url('../api/distribution_agreements_create.dspy')}}",
|
|
||||||
"update_data_url": "{{entire_url('../api/distribution_agreements_update.dspy')}}",
|
|
||||||
"delete_data_url": "{{entire_url('../api/distribution_agreements_delete.dspy')}}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
{
|
|
||||||
"tblname": "sub_distributors",
|
|
||||||
"alias": "sub_distributors_list",
|
|
||||||
"title": "二级分销商管理",
|
|
||||||
"params": {
|
|
||||||
"sortby": [
|
|
||||||
"created_at desc"
|
|
||||||
],
|
|
||||||
"logined_userorgid": "resellerid",
|
|
||||||
"browserfields": {
|
|
||||||
"exclouded": [
|
|
||||||
"created_by",
|
|
||||||
"created_at",
|
|
||||||
"updated_at"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"editexclouded": [
|
|
||||||
"id",
|
|
||||||
"resellerid",
|
|
||||||
"created_by",
|
|
||||||
"created_at",
|
|
||||||
"updated_at"
|
|
||||||
],
|
|
||||||
"editable": {
|
|
||||||
"new_data_url": "{{entire_url('../api/sub_distributors_create.dspy')}}",
|
|
||||||
"update_data_url": "{{entire_url('../api/sub_distributors_update.dspy')}}",
|
|
||||||
"delete_data_url": "{{entire_url('../api/sub_distributors_delete.dspy')}}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
{
|
|
||||||
"tblname": "suppliers",
|
|
||||||
"alias": "suppliers_list",
|
|
||||||
"title": "供应商管理",
|
|
||||||
"params": {
|
|
||||||
"sortby": [
|
|
||||||
"created_at desc"
|
|
||||||
],
|
|
||||||
"logined_userorgid": "resellerid",
|
|
||||||
"browserfields": {
|
|
||||||
"exclouded": [
|
|
||||||
"created_by",
|
|
||||||
"created_at",
|
|
||||||
"updated_at"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"editexclouded": [
|
|
||||||
"id",
|
|
||||||
"resellerid",
|
|
||||||
"created_by",
|
|
||||||
"created_at",
|
|
||||||
"updated_at"
|
|
||||||
],
|
|
||||||
"editable": {
|
|
||||||
"new_data_url": "{{entire_url('../api/suppliers_create.dspy')}}",
|
|
||||||
"update_data_url": "{{entire_url('../api/suppliers_update.dspy')}}",
|
|
||||||
"delete_data_url": "{{entire_url('../api/suppliers_delete.dspy')}}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
{
|
|
||||||
"tblname": "supply_contract_items",
|
|
||||||
"alias": "supply_contract_items_list",
|
|
||||||
"title": "供销合同产品折扣",
|
|
||||||
"params": {
|
|
||||||
"sortby": [
|
|
||||||
"created_at desc"
|
|
||||||
],
|
|
||||||
"logined_userorgid": "resellerid",
|
|
||||||
"browserfields": {
|
|
||||||
"exclouded": [
|
|
||||||
"created_at"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"editexclouded": [
|
|
||||||
"id",
|
|
||||||
"resellerid",
|
|
||||||
"contract_id",
|
|
||||||
"created_at"
|
|
||||||
],
|
|
||||||
"editable": {
|
|
||||||
"new_data_url": "{{entire_url('../api/supply_contract_items_create.dspy')}}",
|
|
||||||
"update_data_url": "{{entire_url('../api/supply_contract_items_update.dspy')}}",
|
|
||||||
"delete_data_url": "{{entire_url('../api/supply_contract_items_delete.dspy')}}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,57 +0,0 @@
|
|||||||
{
|
|
||||||
"tblname": "supply_contracts",
|
|
||||||
"alias": "supply_contracts_list",
|
|
||||||
"title": "供销合同管理",
|
|
||||||
"params": {
|
|
||||||
"sortby": [
|
|
||||||
"created_at desc"
|
|
||||||
],
|
|
||||||
"logined_userorgid": "resellerid",
|
|
||||||
"browserfields": {
|
|
||||||
"exclouded": [
|
|
||||||
"created_by",
|
|
||||||
"created_at",
|
|
||||||
"updated_at"
|
|
||||||
],
|
|
||||||
"alters": {
|
|
||||||
"status": {
|
|
||||||
"uitype": "code",
|
|
||||||
"data": [
|
|
||||||
{
|
|
||||||
"value": "1",
|
|
||||||
"text": "有效"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"value": "0",
|
|
||||||
"text": "无效"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"value": "2",
|
|
||||||
"text": "已过期"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"editexclouded": [
|
|
||||||
"id",
|
|
||||||
"resellerid",
|
|
||||||
"created_by",
|
|
||||||
"created_at",
|
|
||||||
"updated_at"
|
|
||||||
],
|
|
||||||
"subtables": [
|
|
||||||
{
|
|
||||||
"field": "id",
|
|
||||||
"title": "产品折扣",
|
|
||||||
"url": "{{entire_url('../supply_contract_items_list')}}",
|
|
||||||
"subtable": "supply_contract_items"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"editable": {
|
|
||||||
"new_data_url": "{{entire_url('../api/supply_contracts_create.dspy')}}",
|
|
||||||
"update_data_url": "{{entire_url('../api/supply_contracts_update.dspy')}}",
|
|
||||||
"delete_data_url": "{{entire_url('../api/supply_contracts_delete.dspy')}}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,29 +0,0 @@
|
|||||||
{
|
|
||||||
"tblname": "supplychain_accounting",
|
|
||||||
"alias": "supplychain_accounting_list",
|
|
||||||
"title": "供销记账",
|
|
||||||
"params": {
|
|
||||||
"sortby": [
|
|
||||||
"sale_date desc",
|
|
||||||
"created_at desc"
|
|
||||||
],
|
|
||||||
"logined_userorgid": "resellerid",
|
|
||||||
"browserfields": {
|
|
||||||
"exclouded": [
|
|
||||||
"created_by",
|
|
||||||
"created_at"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"editexclouded": [
|
|
||||||
"id",
|
|
||||||
"resellerid",
|
|
||||||
"created_by",
|
|
||||||
"created_at"
|
|
||||||
],
|
|
||||||
"editable": {
|
|
||||||
"new_data_url": "{{entire_url('../api/supplychain_accounting_create.dspy')}}",
|
|
||||||
"update_data_url": "{{entire_url('../api/supplychain_accounting_update.dspy')}}",
|
|
||||||
"delete_data_url": "{{entire_url('../api/supplychain_accounting_delete.dspy')}}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,104 +0,0 @@
|
|||||||
{
|
|
||||||
"summary": [
|
|
||||||
{
|
|
||||||
"name": "distribution_agreement_items",
|
|
||||||
"title": "分销协议产品折扣明细表",
|
|
||||||
"primary": ["id"],
|
|
||||||
"catelog": "relation"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"title": "主键ID",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32,
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "agreement_id",
|
|
||||||
"title": "分销协议ID",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32,
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "resellerid",
|
|
||||||
"title": "所属主分销商机构ID",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32,
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "prodtypeid",
|
|
||||||
"title": "产品分类ID",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "productid",
|
|
||||||
"title": "产品ID",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "discount",
|
|
||||||
"title": "分销折扣",
|
|
||||||
"type": "double",
|
|
||||||
"length": 5,
|
|
||||||
"dec": 4,
|
|
||||||
"nullable": "no",
|
|
||||||
"default": "1.0000"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "settlement_price",
|
|
||||||
"title": "结算单价",
|
|
||||||
"type": "double",
|
|
||||||
"length": 15,
|
|
||||||
"dec": 4
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "remark",
|
|
||||||
"title": "备注",
|
|
||||||
"type": "text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "created_at",
|
|
||||||
"title": "创建时间",
|
|
||||||
"type": "datetime",
|
|
||||||
"nullable": "no"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"indexes": [
|
|
||||||
{
|
|
||||||
"name": "idx_dai_agreement",
|
|
||||||
"idxtype": "index",
|
|
||||||
"idxfields": ["agreement_id"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "idx_dai_product",
|
|
||||||
"idxtype": "index",
|
|
||||||
"idxfields": ["agreement_id", "prodtypeid", "productid"]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"codes": [
|
|
||||||
{
|
|
||||||
"field": "agreement_id",
|
|
||||||
"table": "distribution_agreements",
|
|
||||||
"valuefield": "id",
|
|
||||||
"textfield": "agreement_name"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"field": "prodtypeid",
|
|
||||||
"table": "product_types",
|
|
||||||
"valuefield": "id",
|
|
||||||
"textfield": "type_name"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"field": "productid",
|
|
||||||
"table": "products",
|
|
||||||
"valuefield": "id",
|
|
||||||
"textfield": "product_name"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1,132 +0,0 @@
|
|||||||
{
|
|
||||||
"summary": [
|
|
||||||
{
|
|
||||||
"name": "distribution_agreements",
|
|
||||||
"title": "分销协议表",
|
|
||||||
"primary": ["id"],
|
|
||||||
"catelog": "entity"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"title": "主键ID",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32,
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "resellerid",
|
|
||||||
"title": "所属主分销商机构ID",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32,
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "sub_distributor_id",
|
|
||||||
"title": "二级分销商ID",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32,
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "agreement_code",
|
|
||||||
"title": "协议编号",
|
|
||||||
"type": "str",
|
|
||||||
"length": 64,
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "agreement_name",
|
|
||||||
"title": "协议名称",
|
|
||||||
"type": "str",
|
|
||||||
"length": 255,
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "sign_date",
|
|
||||||
"title": "签署日期",
|
|
||||||
"type": "date"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "start_date",
|
|
||||||
"title": "生效日期",
|
|
||||||
"type": "date",
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "end_date",
|
|
||||||
"title": "到期日期",
|
|
||||||
"type": "date"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "status",
|
|
||||||
"title": "状态",
|
|
||||||
"type": "char",
|
|
||||||
"length": 1,
|
|
||||||
"nullable": "no",
|
|
||||||
"default": "1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "default_discount",
|
|
||||||
"title": "默认分销折扣",
|
|
||||||
"type": "double",
|
|
||||||
"length": 5,
|
|
||||||
"dec": 4,
|
|
||||||
"default": "1.0000"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "remark",
|
|
||||||
"title": "备注",
|
|
||||||
"type": "text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "created_by",
|
|
||||||
"title": "创建人",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "created_at",
|
|
||||||
"title": "创建时间",
|
|
||||||
"type": "datetime",
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "updated_at",
|
|
||||||
"title": "更新时间",
|
|
||||||
"type": "datetime"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"indexes": [
|
|
||||||
{
|
|
||||||
"name": "idx_da_reseller",
|
|
||||||
"idxtype": "index",
|
|
||||||
"idxfields": ["resellerid"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "idx_da_subdist",
|
|
||||||
"idxtype": "index",
|
|
||||||
"idxfields": ["sub_distributor_id"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "idx_da_code",
|
|
||||||
"idxtype": "unique",
|
|
||||||
"idxfields": ["resellerid", "agreement_code"]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"codes": [
|
|
||||||
{
|
|
||||||
"field": "sub_distributor_id",
|
|
||||||
"table": "sub_distributors",
|
|
||||||
"valuefield": "id",
|
|
||||||
"textfield": "sub_dist_name"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"field": "resellerid",
|
|
||||||
"table": "organization",
|
|
||||||
"valuefield": "id",
|
|
||||||
"textfield": "orgname"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1,143 +0,0 @@
|
|||||||
{
|
|
||||||
"summary": [
|
|
||||||
{
|
|
||||||
"name": "sub_distributors",
|
|
||||||
"title": "二级分销商表",
|
|
||||||
"primary": ["id"],
|
|
||||||
"catelog": "entity"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"title": "主键ID",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32,
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "resellerid",
|
|
||||||
"title": "所属主分销商机构ID",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32,
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "sub_dist_code",
|
|
||||||
"title": "二级分销商编号",
|
|
||||||
"type": "str",
|
|
||||||
"length": 64,
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "sub_dist_name",
|
|
||||||
"title": "二级分销商名称",
|
|
||||||
"type": "str",
|
|
||||||
"length": 255,
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "contact_person",
|
|
||||||
"title": "联系人",
|
|
||||||
"type": "str",
|
|
||||||
"length": 100
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "contact_phone",
|
|
||||||
"title": "联系电话",
|
|
||||||
"type": "str",
|
|
||||||
"length": 50
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "contact_email",
|
|
||||||
"title": "联系邮箱",
|
|
||||||
"type": "str",
|
|
||||||
"length": 255
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "address",
|
|
||||||
"title": "地址",
|
|
||||||
"type": "str",
|
|
||||||
"length": 500
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "tax_number",
|
|
||||||
"title": "税号",
|
|
||||||
"type": "str",
|
|
||||||
"length": 64
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "bank_name",
|
|
||||||
"title": "开户银行",
|
|
||||||
"type": "str",
|
|
||||||
"length": 255
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "bank_account",
|
|
||||||
"title": "银行账号",
|
|
||||||
"type": "str",
|
|
||||||
"length": 64
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "managed_by",
|
|
||||||
"title": "负责销售ID",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "status",
|
|
||||||
"title": "状态",
|
|
||||||
"type": "char",
|
|
||||||
"length": 1,
|
|
||||||
"nullable": "no",
|
|
||||||
"default": "1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "remark",
|
|
||||||
"title": "备注",
|
|
||||||
"type": "text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "created_by",
|
|
||||||
"title": "创建人",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "created_at",
|
|
||||||
"title": "创建时间",
|
|
||||||
"type": "datetime",
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "updated_at",
|
|
||||||
"title": "更新时间",
|
|
||||||
"type": "datetime"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"indexes": [
|
|
||||||
{
|
|
||||||
"name": "idx_sd_reseller",
|
|
||||||
"idxtype": "index",
|
|
||||||
"idxfields": ["resellerid"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "idx_sd_code",
|
|
||||||
"idxtype": "unique",
|
|
||||||
"idxfields": ["resellerid", "sub_dist_code"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "idx_sd_manager",
|
|
||||||
"idxtype": "index",
|
|
||||||
"idxfields": ["managed_by"]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"codes": [
|
|
||||||
{
|
|
||||||
"field": "resellerid",
|
|
||||||
"table": "organization",
|
|
||||||
"valuefield": "id",
|
|
||||||
"textfield": "orgname"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1,132 +0,0 @@
|
|||||||
{
|
|
||||||
"summary": [
|
|
||||||
{
|
|
||||||
"name": "suppliers",
|
|
||||||
"title": "供应商表",
|
|
||||||
"primary": ["id"],
|
|
||||||
"catelog": "entity"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"title": "主键ID",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32,
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "resellerid",
|
|
||||||
"title": "所属分销商机构ID",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32,
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "supplier_code",
|
|
||||||
"title": "供应商编号",
|
|
||||||
"type": "str",
|
|
||||||
"length": 64,
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "supplier_name",
|
|
||||||
"title": "供应商名称",
|
|
||||||
"type": "str",
|
|
||||||
"length": 255,
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "contact_person",
|
|
||||||
"title": "联系人",
|
|
||||||
"type": "str",
|
|
||||||
"length": 100
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "contact_phone",
|
|
||||||
"title": "联系电话",
|
|
||||||
"type": "str",
|
|
||||||
"length": 50
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "contact_email",
|
|
||||||
"title": "联系邮箱",
|
|
||||||
"type": "str",
|
|
||||||
"length": 255
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "address",
|
|
||||||
"title": "地址",
|
|
||||||
"type": "str",
|
|
||||||
"length": 500
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "tax_number",
|
|
||||||
"title": "税号",
|
|
||||||
"type": "str",
|
|
||||||
"length": 64
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "bank_name",
|
|
||||||
"title": "开户银行",
|
|
||||||
"type": "str",
|
|
||||||
"length": 255
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "bank_account",
|
|
||||||
"title": "银行账号",
|
|
||||||
"type": "str",
|
|
||||||
"length": 64
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "status",
|
|
||||||
"title": "状态",
|
|
||||||
"type": "char",
|
|
||||||
"length": 1,
|
|
||||||
"nullable": "no",
|
|
||||||
"default": "1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "remark",
|
|
||||||
"title": "备注",
|
|
||||||
"type": "text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "created_by",
|
|
||||||
"title": "创建人",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "created_at",
|
|
||||||
"title": "创建时间",
|
|
||||||
"type": "datetime",
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "updated_at",
|
|
||||||
"title": "更新时间",
|
|
||||||
"type": "datetime"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"indexes": [
|
|
||||||
{
|
|
||||||
"name": "idx_suppliers_reseller",
|
|
||||||
"idxtype": "index",
|
|
||||||
"idxfields": ["resellerid"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "idx_suppliers_code",
|
|
||||||
"idxtype": "unique",
|
|
||||||
"idxfields": ["resellerid", "supplier_code"]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"codes": [
|
|
||||||
{
|
|
||||||
"field": "resellerid",
|
|
||||||
"table": "organization",
|
|
||||||
"valuefield": "id",
|
|
||||||
"textfield": "orgname"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1,104 +0,0 @@
|
|||||||
{
|
|
||||||
"summary": [
|
|
||||||
{
|
|
||||||
"name": "supply_contract_items",
|
|
||||||
"title": "供销合同产品折扣明细表",
|
|
||||||
"primary": ["id"],
|
|
||||||
"catelog": "relation"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"title": "主键ID",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32,
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "contract_id",
|
|
||||||
"title": "供销合同ID",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32,
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "resellerid",
|
|
||||||
"title": "所属分销商机构ID",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32,
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "prodtypeid",
|
|
||||||
"title": "产品分类ID",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "productid",
|
|
||||||
"title": "产品ID",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "discount",
|
|
||||||
"title": "进货折扣",
|
|
||||||
"type": "double",
|
|
||||||
"length": 5,
|
|
||||||
"dec": 4,
|
|
||||||
"nullable": "no",
|
|
||||||
"default": "1.0000"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "settlement_price",
|
|
||||||
"title": "结算单价",
|
|
||||||
"type": "double",
|
|
||||||
"length": 15,
|
|
||||||
"dec": 4
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "remark",
|
|
||||||
"title": "备注",
|
|
||||||
"type": "text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "created_at",
|
|
||||||
"title": "创建时间",
|
|
||||||
"type": "datetime",
|
|
||||||
"nullable": "no"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"indexes": [
|
|
||||||
{
|
|
||||||
"name": "idx_sci_contract",
|
|
||||||
"idxtype": "index",
|
|
||||||
"idxfields": ["contract_id"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "idx_sci_product",
|
|
||||||
"idxtype": "index",
|
|
||||||
"idxfields": ["contract_id", "prodtypeid", "productid"]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"codes": [
|
|
||||||
{
|
|
||||||
"field": "contract_id",
|
|
||||||
"table": "supply_contracts",
|
|
||||||
"valuefield": "id",
|
|
||||||
"textfield": "contract_name"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"field": "prodtypeid",
|
|
||||||
"table": "product_types",
|
|
||||||
"valuefield": "id",
|
|
||||||
"textfield": "type_name"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"field": "productid",
|
|
||||||
"table": "products",
|
|
||||||
"valuefield": "id",
|
|
||||||
"textfield": "product_name"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1,132 +0,0 @@
|
|||||||
{
|
|
||||||
"summary": [
|
|
||||||
{
|
|
||||||
"name": "supply_contracts",
|
|
||||||
"title": "供销合同表",
|
|
||||||
"primary": ["id"],
|
|
||||||
"catelog": "entity"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"title": "主键ID",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32,
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "resellerid",
|
|
||||||
"title": "所属分销商机构ID",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32,
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "supplier_id",
|
|
||||||
"title": "供应商ID",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32,
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "contract_code",
|
|
||||||
"title": "合同编号",
|
|
||||||
"type": "str",
|
|
||||||
"length": 64,
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "contract_name",
|
|
||||||
"title": "合同名称",
|
|
||||||
"type": "str",
|
|
||||||
"length": 255,
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "sign_date",
|
|
||||||
"title": "签署日期",
|
|
||||||
"type": "date"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "start_date",
|
|
||||||
"title": "生效日期",
|
|
||||||
"type": "date",
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "end_date",
|
|
||||||
"title": "到期日期",
|
|
||||||
"type": "date"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "status",
|
|
||||||
"title": "状态",
|
|
||||||
"type": "char",
|
|
||||||
"length": 1,
|
|
||||||
"nullable": "no",
|
|
||||||
"default": "1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "default_discount",
|
|
||||||
"title": "默认折扣",
|
|
||||||
"type": "double",
|
|
||||||
"length": 5,
|
|
||||||
"dec": 4,
|
|
||||||
"default": "1.0000"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "remark",
|
|
||||||
"title": "备注",
|
|
||||||
"type": "text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "created_by",
|
|
||||||
"title": "创建人",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "created_at",
|
|
||||||
"title": "创建时间",
|
|
||||||
"type": "datetime",
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "updated_at",
|
|
||||||
"title": "更新时间",
|
|
||||||
"type": "datetime"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"indexes": [
|
|
||||||
{
|
|
||||||
"name": "idx_sc_reseller",
|
|
||||||
"idxtype": "index",
|
|
||||||
"idxfields": ["resellerid"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "idx_sc_supplier",
|
|
||||||
"idxtype": "index",
|
|
||||||
"idxfields": ["supplier_id"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "idx_sc_code",
|
|
||||||
"idxtype": "unique",
|
|
||||||
"idxfields": ["resellerid", "contract_code"]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"codes": [
|
|
||||||
{
|
|
||||||
"field": "supplier_id",
|
|
||||||
"table": "suppliers",
|
|
||||||
"valuefield": "id",
|
|
||||||
"textfield": "supplier_name"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"field": "resellerid",
|
|
||||||
"table": "organization",
|
|
||||||
"valuefield": "id",
|
|
||||||
"textfield": "orgname"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1,245 +0,0 @@
|
|||||||
{
|
|
||||||
"summary": [
|
|
||||||
{
|
|
||||||
"name": "supplychain_accounting",
|
|
||||||
"title": "供销记账表",
|
|
||||||
"primary": ["id"],
|
|
||||||
"catelog": "relation"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"name": "id",
|
|
||||||
"title": "主键ID",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32,
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "resellerid",
|
|
||||||
"title": "所属主分销商机构ID",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32,
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "supply_contract_id",
|
|
||||||
"title": "供销合同ID",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "supply_contract_item_id",
|
|
||||||
"title": "供销合同产品明细ID",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "distribution_agreement_id",
|
|
||||||
"title": "分销协议ID",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "distribution_agreement_item_id",
|
|
||||||
"title": "分销协议产品明细ID",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "sub_distributor_id",
|
|
||||||
"title": "二级分销商ID",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "supplier_id",
|
|
||||||
"title": "供应商ID",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "prodtypeid",
|
|
||||||
"title": "产品分类ID",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "productid",
|
|
||||||
"title": "产品ID",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "quantity",
|
|
||||||
"title": "数量",
|
|
||||||
"type": "double",
|
|
||||||
"length": 15,
|
|
||||||
"dec": 4,
|
|
||||||
"nullable": "no",
|
|
||||||
"default": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "unit_price",
|
|
||||||
"title": "销售单价",
|
|
||||||
"type": "double",
|
|
||||||
"length": 15,
|
|
||||||
"dec": 4,
|
|
||||||
"nullable": "no",
|
|
||||||
"default": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "supply_discount",
|
|
||||||
"title": "进货折扣",
|
|
||||||
"type": "double",
|
|
||||||
"length": 5,
|
|
||||||
"dec": 4
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "supply_amount",
|
|
||||||
"title": "进货金额(应付供应商)",
|
|
||||||
"type": "double",
|
|
||||||
"length": 15,
|
|
||||||
"dec": 2,
|
|
||||||
"nullable": "no",
|
|
||||||
"default": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "dist_discount",
|
|
||||||
"title": "分销折扣",
|
|
||||||
"type": "double",
|
|
||||||
"length": 5,
|
|
||||||
"dec": 4
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "dist_amount",
|
|
||||||
"title": "分销金额(二级分销商应付)",
|
|
||||||
"type": "double",
|
|
||||||
"length": 15,
|
|
||||||
"dec": 2,
|
|
||||||
"nullable": "no",
|
|
||||||
"default": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "profit_amount",
|
|
||||||
"title": "利润金额",
|
|
||||||
"type": "double",
|
|
||||||
"length": 15,
|
|
||||||
"dec": 2,
|
|
||||||
"nullable": "no",
|
|
||||||
"default": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "sale_date",
|
|
||||||
"title": "销售日期",
|
|
||||||
"type": "date",
|
|
||||||
"nullable": "no"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "source_type",
|
|
||||||
"title": "来源类型",
|
|
||||||
"type": "char",
|
|
||||||
"length": 1,
|
|
||||||
"default": "1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "source_id",
|
|
||||||
"title": "来源记录ID",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "remark",
|
|
||||||
"title": "备注",
|
|
||||||
"type": "text"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "created_by",
|
|
||||||
"title": "创建人",
|
|
||||||
"type": "str",
|
|
||||||
"length": 32
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "created_at",
|
|
||||||
"title": "创建时间",
|
|
||||||
"type": "datetime",
|
|
||||||
"nullable": "no"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"indexes": [
|
|
||||||
{
|
|
||||||
"name": "idx_sa_reseller",
|
|
||||||
"idxtype": "index",
|
|
||||||
"idxfields": ["resellerid"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "idx_sa_sale_date",
|
|
||||||
"idxtype": "index",
|
|
||||||
"idxfields": ["sale_date"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "idx_sa_product",
|
|
||||||
"idxtype": "index",
|
|
||||||
"idxfields": ["productid"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "idx_sa_subdist",
|
|
||||||
"idxtype": "index",
|
|
||||||
"idxfields": ["sub_distributor_id"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "idx_sa_supplier",
|
|
||||||
"idxtype": "index",
|
|
||||||
"idxfields": ["supplier_id"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "idx_sa_source",
|
|
||||||
"idxtype": "index",
|
|
||||||
"idxfields": ["source_type", "source_id"]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"codes": [
|
|
||||||
{
|
|
||||||
"field": "supply_contract_id",
|
|
||||||
"table": "supply_contracts",
|
|
||||||
"valuefield": "id",
|
|
||||||
"textfield": "contract_name"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"field": "distribution_agreement_id",
|
|
||||||
"table": "distribution_agreements",
|
|
||||||
"valuefield": "id",
|
|
||||||
"textfield": "agreement_name"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"field": "sub_distributor_id",
|
|
||||||
"table": "sub_distributors",
|
|
||||||
"valuefield": "id",
|
|
||||||
"textfield": "sub_dist_name"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"field": "supplier_id",
|
|
||||||
"table": "suppliers",
|
|
||||||
"valuefield": "id",
|
|
||||||
"textfield": "supplier_name"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"field": "prodtypeid",
|
|
||||||
"table": "product_types",
|
|
||||||
"valuefield": "id",
|
|
||||||
"textfield": "type_name"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"field": "productid",
|
|
||||||
"table": "products",
|
|
||||||
"valuefield": "id",
|
|
||||||
"textfield": "product_name"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"field": "resellerid",
|
|
||||||
"table": "organization",
|
|
||||||
"valuefield": "id",
|
|
||||||
"textfield": "orgname"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
[build-system]
|
|
||||||
requires = ["setuptools>=45", "wheel"]
|
|
||||||
build-backend = "setuptools.build_meta"
|
|
||||||
|
|
||||||
[project]
|
|
||||||
name = "supplychain"
|
|
||||||
version = "1.0.0"
|
|
||||||
description = "供应商和分销商管理模块 — 供销合同、分销协议、产品折扣及供销记账"
|
|
||||||
requires-python = ">=3.8"
|
|
||||||
dependencies = [
|
|
||||||
"sqlor",
|
|
||||||
"bricks_for_python",
|
|
||||||
]
|
|
||||||
|
|
||||||
[tool.setuptools.packages.find]
|
|
||||||
where = ["."]
|
|
||||||
include = ["supplychain*"]
|
|
||||||
@ -1,208 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
"""
|
|
||||||
supplychain 模块 RBAC 权限管理脚本
|
|
||||||
|
|
||||||
使用方法:
|
|
||||||
cd ~/repos/sage
|
|
||||||
./py3/bin/python ~/repos/supplychain/scripts/load_path.py
|
|
||||||
|
|
||||||
此脚本注册 supplychain 模块的所有 RBAC 权限路径。
|
|
||||||
每次代码变更如有新 path 出现,需同步更新本脚本的 paths 列表。
|
|
||||||
|
|
||||||
路径分类:
|
|
||||||
- any: 静态资源/菜单,无需登录
|
|
||||||
- logined: 需要认证的页面和 API
|
|
||||||
- reseller.operator: 运营角色 — 供应商、供销合同管理
|
|
||||||
- reseller.sale: 销售角色 — 二级分销商、分销协议管理
|
|
||||||
"""
|
|
||||||
|
|
||||||
import subprocess
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
# 查找 Sage 根目录
|
|
||||||
def find_sage_root():
|
|
||||||
candidates = [
|
|
||||||
os.path.expanduser("~/repos/sage"),
|
|
||||||
os.path.expanduser("~/sage"),
|
|
||||||
os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))),
|
|
||||||
]
|
|
||||||
for c in candidates:
|
|
||||||
if os.path.isdir(os.path.join(c, "py3")) and os.path.isdir(os.path.join(c, "wwwroot")):
|
|
||||||
return c
|
|
||||||
return None
|
|
||||||
|
|
||||||
SAGE_ROOT = find_sage_root()
|
|
||||||
if not SAGE_ROOT:
|
|
||||||
print("ERROR: Cannot find Sage root directory")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
SET_PERM = os.path.join(SAGE_ROOT, "py3", "bin", "python")
|
|
||||||
SET_PERM_SCRIPT = os.path.join(SAGE_ROOT, "set_role_perm.py")
|
|
||||||
|
|
||||||
if not os.path.exists(SET_PERM_SCRIPT):
|
|
||||||
print(f"ERROR: set_role_perm.py not found at {SET_PERM_SCRIPT}")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
# ============================================================
|
|
||||||
# 权限路径定义
|
|
||||||
# ============================================================
|
|
||||||
|
|
||||||
# any — 无需登录,静态资源/CRUD 别名目录
|
|
||||||
PATHS_ANY = [
|
|
||||||
"/supplychain/menu.ui",
|
|
||||||
"/supplychain/suppliers_list",
|
|
||||||
"/supplychain/supply_contracts_list",
|
|
||||||
"/supplychain/supply_contract_items_list",
|
|
||||||
"/supplychain/sub_distributors_list",
|
|
||||||
"/supplychain/distribution_agreements_list",
|
|
||||||
"/supplychain/distribution_agreement_items_list",
|
|
||||||
"/supplychain/supplychain_accounting_list",
|
|
||||||
]
|
|
||||||
|
|
||||||
# logined — 需要认证的页面和 API
|
|
||||||
PATHS_LOGINED = [
|
|
||||||
# 模块入口
|
|
||||||
"/supplychain",
|
|
||||||
"/supplychain/index.ui",
|
|
||||||
# 功能页面
|
|
||||||
"/supplychain/suppliers.ui",
|
|
||||||
"/supplychain/supply_contracts.ui",
|
|
||||||
"/supplychain/sub_distributors.ui",
|
|
||||||
"/supplychain/distribution_agreements.ui",
|
|
||||||
"/supplychain/accounting.ui",
|
|
||||||
# CRUD 列表页
|
|
||||||
"/supplychain/suppliers_list/index.ui",
|
|
||||||
"/supplychain/supply_contracts_list/index.ui",
|
|
||||||
"/supplychain/supply_contract_items_list/index.ui",
|
|
||||||
"/supplychain/sub_distributors_list/index.ui",
|
|
||||||
"/supplychain/distribution_agreements_list/index.ui",
|
|
||||||
"/supplychain/distribution_agreement_items_list/index.ui",
|
|
||||||
"/supplychain/supplychain_accounting_list/index.ui",
|
|
||||||
# CRUD API — suppliers
|
|
||||||
"/supplychain/api/suppliers_create.dspy",
|
|
||||||
"/supplychain/api/suppliers_update.dspy",
|
|
||||||
"/supplychain/api/suppliers_delete.dspy",
|
|
||||||
# CRUD API — supply_contracts
|
|
||||||
"/supplychain/api/supply_contracts_create.dspy",
|
|
||||||
"/supplychain/api/supply_contracts_update.dspy",
|
|
||||||
"/supplychain/api/supply_contracts_delete.dspy",
|
|
||||||
# CRUD API — supply_contract_items
|
|
||||||
"/supplychain/api/supply_contract_items_create.dspy",
|
|
||||||
"/supplychain/api/supply_contract_items_update.dspy",
|
|
||||||
"/supplychain/api/supply_contract_items_delete.dspy",
|
|
||||||
# CRUD API — sub_distributors
|
|
||||||
"/supplychain/api/sub_distributors_create.dspy",
|
|
||||||
"/supplychain/api/sub_distributors_update.dspy",
|
|
||||||
"/supplychain/api/sub_distributors_delete.dspy",
|
|
||||||
# CRUD API — distribution_agreements
|
|
||||||
"/supplychain/api/distribution_agreements_create.dspy",
|
|
||||||
"/supplychain/api/distribution_agreements_update.dspy",
|
|
||||||
"/supplychain/api/distribution_agreements_delete.dspy",
|
|
||||||
# CRUD API — distribution_agreement_items
|
|
||||||
"/supplychain/api/distribution_agreement_items_create.dspy",
|
|
||||||
"/supplychain/api/distribution_agreement_items_update.dspy",
|
|
||||||
"/supplychain/api/distribution_agreement_items_delete.dspy",
|
|
||||||
# CRUD API — supplychain_accounting
|
|
||||||
"/supplychain/api/supplychain_accounting_create.dspy",
|
|
||||||
"/supplychain/api/supplychain_accounting_update.dspy",
|
|
||||||
"/supplychain/api/supplychain_accounting_delete.dspy",
|
|
||||||
# 业务 API
|
|
||||||
"/supplychain/api/calculate_accounting.dspy",
|
|
||||||
"/supplychain/api/query_supply_discount.dspy",
|
|
||||||
"/supplychain/api/query_dist_discount.dspy",
|
|
||||||
]
|
|
||||||
|
|
||||||
# 角色专属权限
|
|
||||||
PATHS_OPERATOR = [
|
|
||||||
"/supplychain/suppliers.ui",
|
|
||||||
"/supplychain/suppliers_list",
|
|
||||||
"/supplychain/suppliers_list/index.ui",
|
|
||||||
"/supplychain/api/suppliers_create.dspy",
|
|
||||||
"/supplychain/api/suppliers_update.dspy",
|
|
||||||
"/supplychain/api/suppliers_delete.dspy",
|
|
||||||
"/supplychain/supply_contracts.ui",
|
|
||||||
"/supplychain/supply_contracts_list",
|
|
||||||
"/supplychain/supply_contracts_list/index.ui",
|
|
||||||
"/supplychain/api/supply_contracts_create.dspy",
|
|
||||||
"/supplychain/api/supply_contracts_update.dspy",
|
|
||||||
"/supplychain/api/supply_contracts_delete.dspy",
|
|
||||||
"/supplychain/supply_contract_items_list",
|
|
||||||
"/supplychain/supply_contract_items_list/index.ui",
|
|
||||||
"/supplychain/api/supply_contract_items_create.dspy",
|
|
||||||
"/supplychain/api/supply_contract_items_update.dspy",
|
|
||||||
"/supplychain/api/supply_contract_items_delete.dspy",
|
|
||||||
]
|
|
||||||
|
|
||||||
PATHS_SALE = [
|
|
||||||
"/supplychain/sub_distributors.ui",
|
|
||||||
"/supplychain/sub_distributors_list",
|
|
||||||
"/supplychain/sub_distributors_list/index.ui",
|
|
||||||
"/supplychain/api/sub_distributors_create.dspy",
|
|
||||||
"/supplychain/api/sub_distributors_update.dspy",
|
|
||||||
"/supplychain/api/sub_distributors_delete.dspy",
|
|
||||||
"/supplychain/distribution_agreements.ui",
|
|
||||||
"/supplychain/distribution_agreements_list",
|
|
||||||
"/supplychain/distribution_agreements_list/index.ui",
|
|
||||||
"/supplychain/api/distribution_agreements_create.dspy",
|
|
||||||
"/supplychain/api/distribution_agreements_update.dspy",
|
|
||||||
"/supplychain/api/distribution_agreements_delete.dspy",
|
|
||||||
"/supplychain/distribution_agreement_items_list",
|
|
||||||
"/supplychain/distribution_agreement_items_list/index.ui",
|
|
||||||
"/supplychain/api/distribution_agreement_items_create.dspy",
|
|
||||||
"/supplychain/api/distribution_agreement_items_update.dspy",
|
|
||||||
"/supplychain/api/distribution_agreement_items_delete.dspy",
|
|
||||||
]
|
|
||||||
|
|
||||||
# ============================================================
|
|
||||||
# 执行注册
|
|
||||||
# ============================================================
|
|
||||||
|
|
||||||
def run_set_perm(role, path, verbose=True):
|
|
||||||
"""Register a single permission path."""
|
|
||||||
cmd = [SET_PERM, SET_PERM_SCRIPT, role, path]
|
|
||||||
result = subprocess.run(cmd, capture_output=True, text=True)
|
|
||||||
if verbose:
|
|
||||||
output = result.stdout.strip()
|
|
||||||
if output:
|
|
||||||
print(f" {role}: {path} -> {output}")
|
|
||||||
return result.returncode == 0
|
|
||||||
|
|
||||||
|
|
||||||
def register_role_paths(role, paths):
|
|
||||||
"""Register all paths for a role."""
|
|
||||||
count = 0
|
|
||||||
for path in paths:
|
|
||||||
if run_set_perm(role, path, verbose=False):
|
|
||||||
count += 1
|
|
||||||
print(f" {role}: {count}/{len(paths)} paths registered")
|
|
||||||
return count
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
print(f"Sage root: {SAGE_ROOT}")
|
|
||||||
print(f"set_role_perm.py: {SET_PERM_SCRIPT}")
|
|
||||||
print()
|
|
||||||
|
|
||||||
total = 0
|
|
||||||
|
|
||||||
print("[1/4] Registering 'any' role paths...")
|
|
||||||
total += register_role_paths("any", PATHS_ANY)
|
|
||||||
|
|
||||||
print("[2/4] Registering 'logined' role paths...")
|
|
||||||
total += register_role_paths("logined", PATHS_LOGINED)
|
|
||||||
|
|
||||||
print("[3/4] Registering 'reseller.operator' role paths...")
|
|
||||||
total += register_role_paths("reseller.operator", PATHS_OPERATOR)
|
|
||||||
|
|
||||||
print("[4/4] Registering 'reseller.sale' role paths...")
|
|
||||||
total += register_role_paths("reseller.sale", PATHS_SALE)
|
|
||||||
|
|
||||||
print()
|
|
||||||
print(f"Done. Total {total} permission entries registered.")
|
|
||||||
print()
|
|
||||||
print("NOTE: Restart Sage after permission changes to reload RBAC cache.")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
@ -1,60 +0,0 @@
|
|||||||
---
|
|
||||||
name: supplychain-module
|
|
||||||
version: 1.0.0
|
|
||||||
description: 供应商和分销商管理模块 — 供销合同、分销协议、产品折扣及供销记账
|
|
||||||
trigger_conditions:
|
|
||||||
- 需要管理供应商信息
|
|
||||||
- 需要创建供销合同或分销协议
|
|
||||||
- 需要为产品设置进货或分销折扣
|
|
||||||
- 需要计算产品销售时的供销记账金额
|
|
||||||
---
|
|
||||||
|
|
||||||
# supplychain 模块技能文档
|
|
||||||
|
|
||||||
## 模块概述
|
|
||||||
|
|
||||||
supplychain 模块为分销商提供供应链管理功能,包括供应商管理、供销合同管理、二级分销商管理、分销协议管理,以及产品销售时的供销记账金额计算。
|
|
||||||
|
|
||||||
## 数据表结构
|
|
||||||
|
|
||||||
### 实体表
|
|
||||||
- **suppliers** — 供应商(基本信息、联系方式、财务信息)
|
|
||||||
- **supply_contracts** — 供销合同(运营创建,关联供应商,设置有效期)
|
|
||||||
- **sub_distributors** — 二级分销商(销售创建,基本信息)
|
|
||||||
- **distribution_agreements** — 分销协议(销售创建,关联二级分销商)
|
|
||||||
|
|
||||||
### 关系表
|
|
||||||
- **supply_contract_items** — 供销合同产品折扣明细(合同下的产品级折扣)
|
|
||||||
- **distribution_agreement_items** — 分销协议产品折扣明细(协议下的产品级折扣)
|
|
||||||
- **supplychain_accounting** — 供销记账记录(销售时自动计算)
|
|
||||||
|
|
||||||
## 折扣查找优先级
|
|
||||||
|
|
||||||
无论是进货折扣还是分销折扣,查找优先级均为:
|
|
||||||
1. 精确匹配 productid
|
|
||||||
2. 匹配 prodtypeid(产品分类级折扣)
|
|
||||||
3. 使用合同/协议的 default_discount
|
|
||||||
|
|
||||||
## API 调用
|
|
||||||
|
|
||||||
### 记账计算
|
|
||||||
|
|
||||||
```
|
|
||||||
POST /supplychain/api/calculate_accounting.dspy
|
|
||||||
Body: {productid, prodtypeid?, quantity, unit_price, sub_distributor_id?, sale_date?, ...}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Python 函数调用
|
|
||||||
|
|
||||||
```python
|
|
||||||
# 在 .dspy 文件中
|
|
||||||
record = await calculate_sale_accounting(sor, resellerid, productid, quantity, unit_price,
|
|
||||||
sub_distributor_id, prodtypeid, sale_date, ...)
|
|
||||||
```
|
|
||||||
|
|
||||||
## 注意事项
|
|
||||||
|
|
||||||
- productid 和 prodtypeid 引用 product 模块(即将开发)
|
|
||||||
- 所有数据通过 resellerid 隔离(机构级多租户)
|
|
||||||
- 合同/协议编号自动生成
|
|
||||||
- 折扣值范围 0-1(1.0 表示无折扣)
|
|
||||||
@ -1,252 +0,0 @@
|
|||||||
from ahserver.serverenv import ServerEnv
|
|
||||||
from appPublic.jsonConfig import getConfig
|
|
||||||
from appPublic.dictObject import DictObject
|
|
||||||
from appPublic.uniqueID import getID
|
|
||||||
from sqlor.dbpools import DBPools
|
|
||||||
from datetime import datetime
|
|
||||||
import json
|
|
||||||
|
|
||||||
MODULE_NAME = "supplychain"
|
|
||||||
MODULE_VERSION = "1.0.0"
|
|
||||||
|
|
||||||
|
|
||||||
def _get_dbname():
|
|
||||||
"""Get the database name for the supplychain module."""
|
|
||||||
env = ServerEnv()
|
|
||||||
return env.get_module_dbname('supplychain')
|
|
||||||
|
|
||||||
|
|
||||||
def get_db_context():
|
|
||||||
"""Get a database context manager for the supplychain module."""
|
|
||||||
config = getConfig('.')
|
|
||||||
DBPools(config.databases)
|
|
||||||
dbname = _get_dbname()
|
|
||||||
return db.sqlorContext(dbname)
|
|
||||||
|
|
||||||
|
|
||||||
async def get_active_supply_discount(sor, resellerid, productid, prodtypeid=None, sale_date=None):
|
|
||||||
"""
|
|
||||||
Get active supply contract discount for a product.
|
|
||||||
Priority: exact product > product type > contract default.
|
|
||||||
|
|
||||||
Returns: dict with contract_id, discount, settlement_price, supplier_id
|
|
||||||
"""
|
|
||||||
if sale_date is None:
|
|
||||||
sale_date = datetime.now().strftime("%Y-%m-%d")
|
|
||||||
|
|
||||||
# Try exact product match
|
|
||||||
sql = """SELECT sci.id, sci.contract_id, sci.discount, sci.settlement_price, sc.supplier_id
|
|
||||||
FROM supply_contract_items sci
|
|
||||||
JOIN supply_contracts sc ON sci.contract_id = sc.id
|
|
||||||
WHERE sci.resellerid = ${resellerid}$
|
|
||||||
AND sc.status = '1'
|
|
||||||
AND sc.start_date <= ${sale_date}$
|
|
||||||
AND (sc.end_date IS NULL OR sc.end_date >= ${sale_date}$)
|
|
||||||
AND sci.productid = ${productid}$
|
|
||||||
ORDER BY sc.start_date DESC LIMIT 1"""
|
|
||||||
recs = await sor.sqlExe(sql, {"resellerid": resellerid, "sale_date": sale_date, "productid": productid})
|
|
||||||
|
|
||||||
if not recs and prodtypeid:
|
|
||||||
sql = """SELECT sci.id, sci.contract_id, sci.discount, sci.settlement_price, sc.supplier_id
|
|
||||||
FROM supply_contract_items sci
|
|
||||||
JOIN supply_contracts sc ON sci.contract_id = sc.id
|
|
||||||
WHERE sci.resellerid = ${resellerid}$
|
|
||||||
AND sc.status = '1'
|
|
||||||
AND sc.start_date <= ${sale_date}$
|
|
||||||
AND (sc.end_date IS NULL OR sc.end_date >= ${sale_date}$)
|
|
||||||
AND sci.prodtypeid = ${prodtypeid}$
|
|
||||||
ORDER BY sc.start_date DESC LIMIT 1"""
|
|
||||||
recs = await sor.sqlExe(sql, {"resellerid": resellerid, "sale_date": sale_date, "prodtypeid": prodtypeid})
|
|
||||||
|
|
||||||
if recs:
|
|
||||||
return {
|
|
||||||
"contract_item_id": recs[0].id,
|
|
||||||
"contract_id": recs[0].contract_id,
|
|
||||||
"discount": float(recs[0].discount) if recs[0].discount else 1.0,
|
|
||||||
"settlement_price": float(recs[0].settlement_price) if recs[0].settlement_price else None,
|
|
||||||
"supplier_id": recs[0].supplier_id,
|
|
||||||
}
|
|
||||||
|
|
||||||
# Fallback to contract default
|
|
||||||
sql = """SELECT id, supplier_id, default_discount FROM supply_contracts
|
|
||||||
WHERE resellerid = ${resellerid}$
|
|
||||||
AND status = '1'
|
|
||||||
AND start_date <= ${sale_date}$
|
|
||||||
AND (end_date IS NULL OR end_date >= ${sale_date}$)
|
|
||||||
ORDER BY start_date DESC LIMIT 1"""
|
|
||||||
recs = await sor.sqlExe(sql, {"resellerid": resellerid, "sale_date": sale_date})
|
|
||||||
|
|
||||||
if recs:
|
|
||||||
return {
|
|
||||||
"contract_item_id": None,
|
|
||||||
"contract_id": recs[0].id,
|
|
||||||
"discount": float(recs[0].default_discount) if recs[0].default_discount else 1.0,
|
|
||||||
"settlement_price": None,
|
|
||||||
"supplier_id": recs[0].supplier_id,
|
|
||||||
}
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
async def get_active_dist_discount(sor, resellerid, sub_distributor_id, productid, prodtypeid=None, sale_date=None):
|
|
||||||
"""
|
|
||||||
Get active distribution agreement discount for a product.
|
|
||||||
Priority: exact product > product type > agreement default.
|
|
||||||
|
|
||||||
Returns: dict with agreement_id, discount, settlement_price
|
|
||||||
"""
|
|
||||||
if sale_date is None:
|
|
||||||
sale_date = datetime.now().strftime("%Y-%m-%d")
|
|
||||||
|
|
||||||
# Try exact product match
|
|
||||||
sql = """SELECT dai.id, dai.agreement_id, dai.discount, dai.settlement_price
|
|
||||||
FROM distribution_agreement_items dai
|
|
||||||
JOIN distribution_agreements da ON dai.agreement_id = da.id
|
|
||||||
WHERE dai.resellerid = ${resellerid}$
|
|
||||||
AND da.sub_distributor_id = ${sub_distributor_id}$
|
|
||||||
AND da.status = '1'
|
|
||||||
AND da.start_date <= ${sale_date}$
|
|
||||||
AND (da.end_date IS NULL OR da.end_date >= ${sale_date}$)
|
|
||||||
AND dai.productid = ${productid}$
|
|
||||||
ORDER BY da.start_date DESC LIMIT 1"""
|
|
||||||
ns = {"resellerid": resellerid, "sub_distributor_id": sub_distributor_id,
|
|
||||||
"sale_date": sale_date, "productid": productid}
|
|
||||||
recs = await sor.sqlExe(sql, ns)
|
|
||||||
|
|
||||||
if not recs and prodtypeid:
|
|
||||||
sql = """SELECT dai.id, dai.agreement_id, dai.discount, dai.settlement_price
|
|
||||||
FROM distribution_agreement_items dai
|
|
||||||
JOIN distribution_agreements da ON dai.agreement_id = da.id
|
|
||||||
WHERE dai.resellerid = ${resellerid}$
|
|
||||||
AND da.sub_distributor_id = ${sub_distributor_id}$
|
|
||||||
AND da.status = '1'
|
|
||||||
AND da.start_date <= ${sale_date}$
|
|
||||||
AND (da.end_date IS NULL OR da.end_date >= ${sale_date}$)
|
|
||||||
AND dai.prodtypeid = ${prodtypeid}$
|
|
||||||
ORDER BY da.start_date DESC LIMIT 1"""
|
|
||||||
ns["productid"] = None
|
|
||||||
recs = await sor.sqlExe(sql, ns)
|
|
||||||
|
|
||||||
if recs:
|
|
||||||
return {
|
|
||||||
"agreement_item_id": recs[0].id,
|
|
||||||
"agreement_id": recs[0].agreement_id,
|
|
||||||
"discount": float(recs[0].discount) if recs[0].discount else 1.0,
|
|
||||||
"settlement_price": float(recs[0].settlement_price) if recs[0].settlement_price else None,
|
|
||||||
}
|
|
||||||
|
|
||||||
# Fallback to agreement default
|
|
||||||
sql = """SELECT id, default_discount FROM distribution_agreements
|
|
||||||
WHERE resellerid = ${resellerid}$
|
|
||||||
AND sub_distributor_id = ${sub_distributor_id}$
|
|
||||||
AND status = '1'
|
|
||||||
AND start_date <= ${sale_date}$
|
|
||||||
AND (end_date IS NULL OR end_date >= ${sale_date}$)
|
|
||||||
ORDER BY start_date DESC LIMIT 1"""
|
|
||||||
recs = await sor.sqlExe(sql, {"resellerid": resellerid,
|
|
||||||
"sub_distributor_id": sub_distributor_id,
|
|
||||||
"sale_date": sale_date})
|
|
||||||
|
|
||||||
if recs:
|
|
||||||
return {
|
|
||||||
"agreement_item_id": None,
|
|
||||||
"agreement_id": recs[0].id,
|
|
||||||
"discount": float(recs[0].default_discount) if recs[0].default_discount else 1.0,
|
|
||||||
"settlement_price": None,
|
|
||||||
}
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
async def calculate_sale_accounting(sor, resellerid, productid, quantity, unit_price,
|
|
||||||
sub_distributor_id=None, prodtypeid=None,
|
|
||||||
sale_date=None, source_type="2", source_id=None,
|
|
||||||
created_by=None, remark=""):
|
|
||||||
"""
|
|
||||||
Calculate and record accounting for a product sale.
|
|
||||||
|
|
||||||
Returns: the created accounting record as dict
|
|
||||||
"""
|
|
||||||
if sale_date is None:
|
|
||||||
sale_date = datetime.now().strftime("%Y-%m-%d")
|
|
||||||
|
|
||||||
total_amount = quantity * unit_price
|
|
||||||
|
|
||||||
# Get supply discount
|
|
||||||
supply_info = await get_active_supply_discount(sor, resellerid, productid, prodtypeid, sale_date)
|
|
||||||
|
|
||||||
supply_contract_id = None
|
|
||||||
supply_contract_item_id = None
|
|
||||||
supplier_id = None
|
|
||||||
supply_discount = 1.0
|
|
||||||
supply_amount = total_amount
|
|
||||||
|
|
||||||
if supply_info:
|
|
||||||
supply_contract_id = supply_info["contract_id"]
|
|
||||||
supply_contract_item_id = supply_info["contract_item_id"]
|
|
||||||
supplier_id = supply_info["supplier_id"]
|
|
||||||
supply_discount = supply_info["discount"]
|
|
||||||
if supply_info["settlement_price"]:
|
|
||||||
supply_amount = supply_info["settlement_price"] * quantity
|
|
||||||
else:
|
|
||||||
supply_amount = total_amount * supply_discount
|
|
||||||
|
|
||||||
# Get distribution discount
|
|
||||||
distribution_agreement_id = None
|
|
||||||
distribution_agreement_item_id = None
|
|
||||||
dist_discount = 1.0
|
|
||||||
dist_amount = total_amount
|
|
||||||
|
|
||||||
if sub_distributor_id:
|
|
||||||
dist_info = await get_active_dist_discount(sor, resellerid, sub_distributor_id,
|
|
||||||
productid, prodtypeid, sale_date)
|
|
||||||
if dist_info:
|
|
||||||
distribution_agreement_id = dist_info["agreement_id"]
|
|
||||||
distribution_agreement_item_id = dist_info["agreement_item_id"]
|
|
||||||
dist_discount = dist_info["discount"]
|
|
||||||
if dist_info["settlement_price"]:
|
|
||||||
dist_amount = dist_info["settlement_price"] * quantity
|
|
||||||
else:
|
|
||||||
dist_amount = total_amount * dist_discount
|
|
||||||
|
|
||||||
profit_amount = dist_amount - supply_amount
|
|
||||||
|
|
||||||
# Create accounting record
|
|
||||||
accounting_id = getID()
|
|
||||||
record = {
|
|
||||||
"id": accounting_id,
|
|
||||||
"resellerid": resellerid,
|
|
||||||
"supply_contract_id": supply_contract_id,
|
|
||||||
"supply_contract_item_id": supply_contract_item_id,
|
|
||||||
"distribution_agreement_id": distribution_agreement_id,
|
|
||||||
"distribution_agreement_item_id": distribution_agreement_item_id,
|
|
||||||
"sub_distributor_id": sub_distributor_id,
|
|
||||||
"supplier_id": supplier_id,
|
|
||||||
"prodtypeid": prodtypeid,
|
|
||||||
"productid": productid,
|
|
||||||
"quantity": quantity,
|
|
||||||
"unit_price": unit_price,
|
|
||||||
"supply_discount": supply_discount,
|
|
||||||
"supply_amount": supply_amount,
|
|
||||||
"dist_discount": dist_discount,
|
|
||||||
"dist_amount": dist_amount,
|
|
||||||
"profit_amount": profit_amount,
|
|
||||||
"sale_date": sale_date,
|
|
||||||
"source_type": source_type,
|
|
||||||
"source_id": source_id,
|
|
||||||
"remark": remark,
|
|
||||||
"created_by": created_by,
|
|
||||||
"created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
||||||
}
|
|
||||||
|
|
||||||
await sor.C("supplychain_accounting", record)
|
|
||||||
return record
|
|
||||||
|
|
||||||
|
|
||||||
def load_supplychain():
|
|
||||||
"""Register all functions with ServerEnv."""
|
|
||||||
env = ServerEnv()
|
|
||||||
env.get_active_supply_discount = get_active_supply_discount
|
|
||||||
env.get_active_dist_discount = get_active_dist_discount
|
|
||||||
env.calculate_sale_accounting = calculate_sale_accounting
|
|
||||||
return True
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
{
|
|
||||||
"widgettype": "VBox",
|
|
||||||
"options": {
|
|
||||||
"width": "100%",
|
|
||||||
"height": "100%",
|
|
||||||
"padding": "16px"
|
|
||||||
},
|
|
||||||
"subwidgets": [
|
|
||||||
{
|
|
||||||
"widgettype": "Text",
|
|
||||||
"options": {
|
|
||||||
"text": "供销记账",
|
|
||||||
"fontSize": "20px",
|
|
||||||
"fontWeight": "bold",
|
|
||||||
"marginBottom": "16px"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"widgettype": "DataViewer",
|
|
||||||
"options": {
|
|
||||||
"url": "{{entire_url('supplychain_accounting_list/index.ui')}}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1,222 +0,0 @@
|
|||||||
import json
|
|
||||||
from appPublic.uniqueID import getID
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
async def main(request, params_kw):
|
|
||||||
"""
|
|
||||||
产品销售时调用此API计算供销记账金额。
|
|
||||||
|
|
||||||
输入参数:
|
|
||||||
productid: 产品ID
|
|
||||||
prodtypeid: 产品分类ID (可选)
|
|
||||||
quantity: 销售数量
|
|
||||||
unit_price: 销售单价
|
|
||||||
sub_distributor_id: 二级分销商ID (可选, 如果是直接销售则为空)
|
|
||||||
sale_date: 销售日期 (可选, 默认今天)
|
|
||||||
source_type: 来源类型 (1=手动, 2=API调用)
|
|
||||||
source_id: 来源记录ID (可选)
|
|
||||||
|
|
||||||
计算逻辑:
|
|
||||||
1. 查找有效的供销合同及对应产品折扣
|
|
||||||
2. 查找有效的分销协议及对应产品折扣 (如果有二级分销商)
|
|
||||||
3. 计算: 进货金额 = 单价 * 数量 * 进货折扣
|
|
||||||
4. 计算: 分销金额 = 单价 * 数量 * 分销折扣
|
|
||||||
5. 计算: 利润金额 = 分销金额 - 进货金额
|
|
||||||
6. 创建记账记录
|
|
||||||
|
|
||||||
返回: 记账记录数据
|
|
||||||
"""
|
|
||||||
user_id = await get_user()
|
|
||||||
user_orgid = await get_userorgid()
|
|
||||||
dbname = get_module_dbname('supplychain')
|
|
||||||
|
|
||||||
# Parse input
|
|
||||||
data = params_kw.get("data", "{}")
|
|
||||||
if isinstance(data, str):
|
|
||||||
data = json.loads(data)
|
|
||||||
|
|
||||||
productid = data.get("productid")
|
|
||||||
prodtypeid = data.get("prodtypeid")
|
|
||||||
quantity = float(data.get("quantity", 0))
|
|
||||||
unit_price = float(data.get("unit_price", 0))
|
|
||||||
sub_distributor_id = data.get("sub_distributor_id")
|
|
||||||
sale_date = data.get("sale_date", datetime.now().strftime("%Y-%m-%d"))
|
|
||||||
source_type = data.get("source_type", "2")
|
|
||||||
source_id = data.get("source_id")
|
|
||||||
remark = data.get("remark", "")
|
|
||||||
|
|
||||||
if not productid or quantity <= 0 or unit_price <= 0:
|
|
||||||
return json.dumps({"status": "error", "message": "缺少必要参数: productid, quantity, unit_price"})
|
|
||||||
|
|
||||||
config = getConfig(".")
|
|
||||||
DBPools(config.databases)
|
|
||||||
total_amount = quantity * unit_price
|
|
||||||
|
|
||||||
async with db.sqlorContext(dbname) as sor:
|
|
||||||
# Step 1: Find active supply contract with product discount
|
|
||||||
# Priority: exact product > product type > default contract discount
|
|
||||||
supply_contract_id = None
|
|
||||||
supply_contract_item_id = None
|
|
||||||
supplier_id = None
|
|
||||||
supply_discount = 1.0
|
|
||||||
supply_amount = total_amount
|
|
||||||
|
|
||||||
# Find supply contract items matching this product
|
|
||||||
if prodtypeid:
|
|
||||||
sql_sci = """SELECT sci.id, sci.contract_id, sci.discount, sci.settlement_price, sc.supplier_id
|
|
||||||
FROM supply_contract_items sci
|
|
||||||
JOIN supply_contracts sc ON sci.contract_id = sc.id
|
|
||||||
WHERE sci.resellerid = ${resellerid}$
|
|
||||||
AND sc.status = '1'
|
|
||||||
AND sc.start_date <= ${sale_date}$
|
|
||||||
AND (sc.end_date IS NULL OR sc.end_date >= ${sale_date}$)
|
|
||||||
AND sci.productid = ${productid}$
|
|
||||||
ORDER BY sci.created_at DESC LIMIT 1"""
|
|
||||||
ns_sci = {"resellerid": user_orgid, "sale_date": sale_date, "productid": productid}
|
|
||||||
sci_recs = await sor.sqlExe(sql_sci, ns_sci)
|
|
||||||
|
|
||||||
if not prodtypeid or not sci_recs:
|
|
||||||
sql_sci = """SELECT sci.id, sci.contract_id, sci.discount, sci.settlement_price, sc.supplier_id
|
|
||||||
FROM supply_contract_items sci
|
|
||||||
JOIN supply_contracts sc ON sci.contract_id = sc.id
|
|
||||||
WHERE sci.resellerid = ${resellerid}$
|
|
||||||
AND sc.status = '1'
|
|
||||||
AND sc.start_date <= ${sale_date}$
|
|
||||||
AND (sc.end_date IS NULL OR sc.end_date >= ${sale_date}$)
|
|
||||||
AND sci.prodtypeid = ${prodtypeid}$
|
|
||||||
ORDER BY sci.created_at DESC LIMIT 1"""
|
|
||||||
ns_sci = {"resellerid": user_orgid, "sale_date": sale_date, "prodtypeid": prodtypeid}
|
|
||||||
sci_recs = await sor.sqlExe(sql_sci, ns_sci)
|
|
||||||
|
|
||||||
if sci_recs:
|
|
||||||
supply_contract_item_id = sci_recs[0].id
|
|
||||||
supply_contract_id = sci_recs[0].contract_id
|
|
||||||
supplier_id = sci_recs[0].supplier_id
|
|
||||||
supply_discount = float(sci_recs[0].discount) if sci_recs[0].discount else 1.0
|
|
||||||
if sci_recs[0].settlement_price:
|
|
||||||
supply_amount = float(sci_recs[0].settlement_price) * quantity
|
|
||||||
else:
|
|
||||||
supply_amount = total_amount * supply_discount
|
|
||||||
else:
|
|
||||||
# Fallback: find any active supply contract with default discount
|
|
||||||
sql_sc = """SELECT id, supplier_id, default_discount FROM supply_contracts
|
|
||||||
WHERE resellerid = ${resellerid}$
|
|
||||||
AND status = '1'
|
|
||||||
AND start_date <= ${sale_date}$
|
|
||||||
AND (end_date IS NULL OR end_date >= ${sale_date}$)
|
|
||||||
ORDER BY created_at DESC LIMIT 1"""
|
|
||||||
sc_recs = await sor.sqlExe(sql_sc, {"resellerid": user_orgid, "sale_date": sale_date})
|
|
||||||
if sc_recs:
|
|
||||||
supply_contract_id = sc_recs[0].id
|
|
||||||
supplier_id = sc_recs[0].supplier_id
|
|
||||||
supply_discount = float(sc_recs[0].default_discount) if sc_recs[0].default_discount else 1.0
|
|
||||||
supply_amount = total_amount * supply_discount
|
|
||||||
|
|
||||||
# Step 2: Find active distribution agreement with product discount (if sub_distributor)
|
|
||||||
distribution_agreement_id = None
|
|
||||||
distribution_agreement_item_id = None
|
|
||||||
dist_discount = 1.0
|
|
||||||
dist_amount = total_amount
|
|
||||||
|
|
||||||
if sub_distributor_id:
|
|
||||||
# Find distribution agreement items matching this product
|
|
||||||
sql_dai = """SELECT dai.id, dai.agreement_id, dai.discount, dai.settlement_price
|
|
||||||
FROM distribution_agreement_items dai
|
|
||||||
JOIN distribution_agreements da ON dai.agreement_id = da.id
|
|
||||||
WHERE dai.resellerid = ${resellerid}$
|
|
||||||
AND da.sub_distributor_id = ${sub_distributor_id}$
|
|
||||||
AND da.status = '1'
|
|
||||||
AND da.start_date <= ${sale_date}$
|
|
||||||
AND (da.end_date IS NULL OR da.end_date >= ${sale_date}$)
|
|
||||||
AND dai.productid = ${productid}$
|
|
||||||
ORDER BY dai.created_at DESC LIMIT 1"""
|
|
||||||
ns_dai = {"resellerid": user_orgid, "sub_distributor_id": sub_distributor_id,
|
|
||||||
"sale_date": sale_date, "productid": productid}
|
|
||||||
dai_recs = await sor.sqlExe(sql_dai, ns_dai)
|
|
||||||
|
|
||||||
if not dai_recs and prodtypeid:
|
|
||||||
sql_dai = """SELECT dai.id, dai.agreement_id, dai.discount, dai.settlement_price
|
|
||||||
FROM distribution_agreement_items dai
|
|
||||||
JOIN distribution_agreements da ON dai.agreement_id = da.id
|
|
||||||
WHERE dai.resellerid = ${resellerid}$
|
|
||||||
AND da.sub_distributor_id = ${sub_distributor_id}$
|
|
||||||
AND da.status = '1'
|
|
||||||
AND da.start_date <= ${sale_date}$
|
|
||||||
AND (da.end_date IS NULL OR da.end_date >= ${sale_date}$)
|
|
||||||
AND dai.prodtypeid = ${prodtypeid}$
|
|
||||||
ORDER BY dai.created_at DESC LIMIT 1"""
|
|
||||||
ns_dai["productid"] = None
|
|
||||||
dai_recs = await sor.sqlExe(sql_dai, ns_dai)
|
|
||||||
|
|
||||||
if dai_recs:
|
|
||||||
distribution_agreement_item_id = dai_recs[0].id
|
|
||||||
distribution_agreement_id = dai_recs[0].agreement_id
|
|
||||||
dist_discount = float(dai_recs[0].discount) if dai_recs[0].discount else 1.0
|
|
||||||
if dai_recs[0].settlement_price:
|
|
||||||
dist_amount = float(dai_recs[0].settlement_price) * quantity
|
|
||||||
else:
|
|
||||||
dist_amount = total_amount * dist_discount
|
|
||||||
else:
|
|
||||||
# Fallback: find active distribution agreement with default discount
|
|
||||||
sql_da = """SELECT id, default_discount FROM distribution_agreements
|
|
||||||
WHERE resellerid = ${resellerid}$
|
|
||||||
AND sub_distributor_id = ${sub_distributor_id}$
|
|
||||||
AND status = '1'
|
|
||||||
AND start_date <= ${sale_date}$
|
|
||||||
AND (end_date IS NULL OR end_date >= ${sale_date}$)
|
|
||||||
ORDER BY created_at DESC LIMIT 1"""
|
|
||||||
da_recs = await sor.sqlExe(sql_da, {"resellerid": user_orgid,
|
|
||||||
"sub_distributor_id": sub_distributor_id,
|
|
||||||
"sale_date": sale_date})
|
|
||||||
if da_recs:
|
|
||||||
distribution_agreement_id = da_recs[0].id
|
|
||||||
dist_discount = float(da_recs[0].default_discount) if da_recs[0].default_discount else 1.0
|
|
||||||
dist_amount = total_amount * dist_discount
|
|
||||||
|
|
||||||
# Step 3: Calculate profit
|
|
||||||
profit_amount = dist_amount - supply_amount
|
|
||||||
|
|
||||||
# Step 4: Create accounting record
|
|
||||||
accounting_id = getID()
|
|
||||||
record = {
|
|
||||||
"id": accounting_id,
|
|
||||||
"resellerid": user_orgid,
|
|
||||||
"supply_contract_id": supply_contract_id,
|
|
||||||
"supply_contract_item_id": supply_contract_item_id,
|
|
||||||
"distribution_agreement_id": distribution_agreement_id,
|
|
||||||
"distribution_agreement_item_id": distribution_agreement_item_id,
|
|
||||||
"sub_distributor_id": sub_distributor_id,
|
|
||||||
"supplier_id": supplier_id,
|
|
||||||
"prodtypeid": prodtypeid,
|
|
||||||
"productid": productid,
|
|
||||||
"quantity": quantity,
|
|
||||||
"unit_price": unit_price,
|
|
||||||
"supply_discount": supply_discount,
|
|
||||||
"supply_amount": supply_amount,
|
|
||||||
"dist_discount": dist_discount,
|
|
||||||
"dist_amount": dist_amount,
|
|
||||||
"profit_amount": profit_amount,
|
|
||||||
"sale_date": sale_date,
|
|
||||||
"source_type": source_type,
|
|
||||||
"source_id": source_id,
|
|
||||||
"remark": remark,
|
|
||||||
"created_by": user_id,
|
|
||||||
"created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
||||||
}
|
|
||||||
|
|
||||||
await sor.C("supplychain_accounting", record)
|
|
||||||
|
|
||||||
result = {
|
|
||||||
"status": "ok",
|
|
||||||
"data": record,
|
|
||||||
"summary": {
|
|
||||||
"total_amount": total_amount,
|
|
||||||
"supply_amount": supply_amount,
|
|
||||||
"dist_amount": dist_amount,
|
|
||||||
"profit_amount": profit_amount,
|
|
||||||
"supply_discount": supply_discount,
|
|
||||||
"dist_discount": dist_discount
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return json.dumps(result)
|
|
||||||
@ -1,23 +0,0 @@
|
|||||||
import json
|
|
||||||
from appPublic.uniqueID import getID
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
async def main(request, params_kw):
|
|
||||||
"""Create a new distribution_agreement_items record."""
|
|
||||||
user_id = await get_user()
|
|
||||||
user_orgid = await get_userorgid()
|
|
||||||
dbname = get_module_dbname('supplychain')
|
|
||||||
|
|
||||||
data = params_kw.get("data", "{}")
|
|
||||||
if isinstance(data, str):
|
|
||||||
data = json.loads(data)
|
|
||||||
|
|
||||||
data["id"] = getID()
|
|
||||||
data["resellerid"] = user_orgid
|
|
||||||
data["created_at"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
||||||
|
|
||||||
config = getConfig(".")
|
|
||||||
DBPools(config.databases)
|
|
||||||
async with db.sqlorContext(dbname) as sor:
|
|
||||||
await sor.C("distribution_agreement_items", data)
|
|
||||||
return json.dumps({"status": "ok", "data": data})
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
import json
|
|
||||||
|
|
||||||
async def main(request, params_kw):
|
|
||||||
"""Delete a distribution_agreement_items record."""
|
|
||||||
dbname = get_module_dbname('supplychain')
|
|
||||||
|
|
||||||
data = params_kw.get("data", "{}")
|
|
||||||
if isinstance(data, str):
|
|
||||||
data = json.loads(data)
|
|
||||||
|
|
||||||
record_id = data.get("id")
|
|
||||||
if not record_id:
|
|
||||||
return json.dumps({"status": "error", "message": "Missing record id"})
|
|
||||||
|
|
||||||
config = getConfig(".")
|
|
||||||
DBPools(config.databases)
|
|
||||||
async with db.sqlorContext(dbname) as sor:
|
|
||||||
await sor.D("distribution_agreement_items", {"id": record_id})
|
|
||||||
return json.dumps({"status": "ok", "message": "Deleted successfully"})
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
import json
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
async def main(request, params_kw):
|
|
||||||
"""Update a distribution_agreement_items record."""
|
|
||||||
user_id = await get_user()
|
|
||||||
dbname = get_module_dbname('supplychain')
|
|
||||||
|
|
||||||
data = params_kw.get("data", "{}")
|
|
||||||
if isinstance(data, str):
|
|
||||||
data = json.loads(data)
|
|
||||||
|
|
||||||
record_id = data.get("id")
|
|
||||||
if not record_id:
|
|
||||||
return json.dumps({"status": "error", "message": "Missing record id"})
|
|
||||||
|
|
||||||
data["updated_at"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
||||||
|
|
||||||
# Remove fields that should not be updated
|
|
||||||
for key in ["id", "resellerid", "created_by", "created_at"]:
|
|
||||||
data.pop(key, None)
|
|
||||||
|
|
||||||
config = getConfig(".")
|
|
||||||
DBPools(config.databases)
|
|
||||||
async with db.sqlorContext(dbname) as sor:
|
|
||||||
await sor.U("distribution_agreement_items", data)
|
|
||||||
return json.dumps({"status": "ok", "data": data})
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
import json
|
|
||||||
from appPublic.uniqueID import getID
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
async def main(request, params_kw):
|
|
||||||
"""Create a new distribution_agreements record."""
|
|
||||||
user_id = await get_user()
|
|
||||||
user_orgid = await get_userorgid()
|
|
||||||
dbname = get_module_dbname('supplychain')
|
|
||||||
|
|
||||||
data = params_kw.get("data", "{}")
|
|
||||||
if isinstance(data, str):
|
|
||||||
data = json.loads(data)
|
|
||||||
|
|
||||||
data["id"] = getID()
|
|
||||||
data["resellerid"] = user_orgid
|
|
||||||
data["created_by"] = user_id
|
|
||||||
data["created_at"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
||||||
|
|
||||||
# Auto-generate agreement code
|
|
||||||
if not data.get("agreement_code"):
|
|
||||||
data["agreement_code"] = f"DA-{datetime.now().strftime('%Y%m%d')}-{getID()[:4].upper()}"
|
|
||||||
|
|
||||||
config = getConfig(".")
|
|
||||||
DBPools(config.databases)
|
|
||||||
async with db.sqlorContext(dbname) as sor:
|
|
||||||
await sor.C("distribution_agreements", data)
|
|
||||||
return json.dumps({"status": "ok", "data": data})
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
import json
|
|
||||||
|
|
||||||
async def main(request, params_kw):
|
|
||||||
"""Delete a distribution_agreements record."""
|
|
||||||
dbname = get_module_dbname('supplychain')
|
|
||||||
|
|
||||||
data = params_kw.get("data", "{}")
|
|
||||||
if isinstance(data, str):
|
|
||||||
data = json.loads(data)
|
|
||||||
|
|
||||||
record_id = data.get("id")
|
|
||||||
if not record_id:
|
|
||||||
return json.dumps({"status": "error", "message": "Missing record id"})
|
|
||||||
|
|
||||||
config = getConfig(".")
|
|
||||||
DBPools(config.databases)
|
|
||||||
async with db.sqlorContext(dbname) as sor:
|
|
||||||
await sor.D("distribution_agreements", {"id": record_id})
|
|
||||||
return json.dumps({"status": "ok", "message": "Deleted successfully"})
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
import json
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
async def main(request, params_kw):
|
|
||||||
"""Update a distribution_agreements record."""
|
|
||||||
user_id = await get_user()
|
|
||||||
dbname = get_module_dbname('supplychain')
|
|
||||||
|
|
||||||
data = params_kw.get("data", "{}")
|
|
||||||
if isinstance(data, str):
|
|
||||||
data = json.loads(data)
|
|
||||||
|
|
||||||
record_id = data.get("id")
|
|
||||||
if not record_id:
|
|
||||||
return json.dumps({"status": "error", "message": "Missing record id"})
|
|
||||||
|
|
||||||
data["updated_at"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
||||||
|
|
||||||
# Remove fields that should not be updated
|
|
||||||
for key in ["id", "resellerid", "created_by", "created_at"]:
|
|
||||||
data.pop(key, None)
|
|
||||||
|
|
||||||
config = getConfig(".")
|
|
||||||
DBPools(config.databases)
|
|
||||||
async with db.sqlorContext(dbname) as sor:
|
|
||||||
await sor.U("distribution_agreements", data)
|
|
||||||
return json.dumps({"status": "ok", "data": data})
|
|
||||||
@ -1,74 +0,0 @@
|
|||||||
import json
|
|
||||||
|
|
||||||
async def main(request, params_kw):
|
|
||||||
"""
|
|
||||||
查询某二级分销商在某产品上的分销协议折扣。
|
|
||||||
|
|
||||||
参数: sub_distributor_id, productid, prodtypeid(可选)
|
|
||||||
|
|
||||||
折扣查找优先级:
|
|
||||||
1. 精确匹配 productid
|
|
||||||
2. 匹配 prodtypeid
|
|
||||||
3. 使用协议默认折扣
|
|
||||||
"""
|
|
||||||
user_orgid = await get_userorgid()
|
|
||||||
dbname = get_module_dbname('supplychain')
|
|
||||||
|
|
||||||
sub_distributor_id = params_kw.get("sub_distributor_id")
|
|
||||||
productid = params_kw.get("productid")
|
|
||||||
prodtypeid = params_kw.get("prodtypeid")
|
|
||||||
|
|
||||||
if not sub_distributor_id or not productid:
|
|
||||||
return json.dumps({"status": "error", "message": "缺少sub_distributor_id或productid参数"})
|
|
||||||
|
|
||||||
config = getConfig(".")
|
|
||||||
DBPools(config.databases)
|
|
||||||
|
|
||||||
async with db.sqlorContext(dbname) as sor:
|
|
||||||
# Try exact product match
|
|
||||||
sql = """SELECT dai.id, dai.agreement_id, dai.discount, dai.settlement_price,
|
|
||||||
da.agreement_code, da.agreement_name
|
|
||||||
FROM distribution_agreement_items dai
|
|
||||||
JOIN distribution_agreements da ON dai.agreement_id = da.id
|
|
||||||
WHERE dai.resellerid = ${resellerid}$
|
|
||||||
AND da.sub_distributor_id = ${sub_distributor_id}$
|
|
||||||
AND da.status = '1'
|
|
||||||
AND da.start_date <= CURDATE()
|
|
||||||
AND (da.end_date IS NULL OR da.end_date >= CURDATE())
|
|
||||||
AND dai.productid = ${productid}$
|
|
||||||
ORDER BY da.start_date DESC"""
|
|
||||||
recs = await sor.sqlExe(sql, {"resellerid": user_orgid,
|
|
||||||
"sub_distributor_id": sub_distributor_id,
|
|
||||||
"productid": productid})
|
|
||||||
|
|
||||||
if not recs and prodtypeid:
|
|
||||||
sql = """SELECT dai.id, dai.agreement_id, dai.discount, dai.settlement_price,
|
|
||||||
da.agreement_code, da.agreement_name
|
|
||||||
FROM distribution_agreement_items dai
|
|
||||||
JOIN distribution_agreements da ON dai.agreement_id = da.id
|
|
||||||
WHERE dai.resellerid = ${resellerid}$
|
|
||||||
AND da.sub_distributor_id = ${sub_distributor_id}$
|
|
||||||
AND da.status = '1'
|
|
||||||
AND da.start_date <= CURDATE()
|
|
||||||
AND (da.end_date IS NULL OR da.end_date >= CURDATE())
|
|
||||||
AND dai.prodtypeid = ${prodtypeid}$
|
|
||||||
ORDER BY da.start_date DESC"""
|
|
||||||
recs = await sor.sqlExe(sql, {"resellerid": user_orgid,
|
|
||||||
"sub_distributor_id": sub_distributor_id,
|
|
||||||
"prodtypeid": prodtypeid})
|
|
||||||
|
|
||||||
if not recs:
|
|
||||||
sql = """SELECT id as agreement_id, agreement_code, agreement_name,
|
|
||||||
default_discount as discount, NULL as settlement_price
|
|
||||||
FROM distribution_agreements
|
|
||||||
WHERE resellerid = ${resellerid}$
|
|
||||||
AND sub_distributor_id = ${sub_distributor_id}$
|
|
||||||
AND status = '1'
|
|
||||||
AND start_date <= CURDATE()
|
|
||||||
AND (end_date IS NULL OR end_date >= CURDATE())
|
|
||||||
ORDER BY start_date DESC"""
|
|
||||||
recs = await sor.sqlExe(sql, {"resellerid": user_orgid,
|
|
||||||
"sub_distributor_id": sub_distributor_id})
|
|
||||||
|
|
||||||
result = [dict(r) for r in recs] if recs else []
|
|
||||||
return json.dumps({"status": "ok", "data": result})
|
|
||||||
@ -1,70 +0,0 @@
|
|||||||
import json
|
|
||||||
|
|
||||||
async def main(request, params_kw):
|
|
||||||
"""
|
|
||||||
查询某产品在有效供销合同下的折扣信息。
|
|
||||||
|
|
||||||
参数: productid, prodtypeid(可选)
|
|
||||||
|
|
||||||
折扣查找优先级:
|
|
||||||
1. 精确匹配 productid
|
|
||||||
2. 匹配 prodtypeid
|
|
||||||
3. 使用合同默认折扣
|
|
||||||
"""
|
|
||||||
user_orgid = await get_userorgid()
|
|
||||||
dbname = get_module_dbname('supplychain')
|
|
||||||
|
|
||||||
productid = params_kw.get("productid")
|
|
||||||
prodtypeid = params_kw.get("prodtypeid")
|
|
||||||
|
|
||||||
if not productid:
|
|
||||||
return json.dumps({"status": "error", "message": "缺少productid参数"})
|
|
||||||
|
|
||||||
config = getConfig(".")
|
|
||||||
DBPools(config.databases)
|
|
||||||
|
|
||||||
async with db.sqlorContext(dbname) as sor:
|
|
||||||
# Try exact product match
|
|
||||||
sql = """SELECT sci.id, sci.contract_id, sci.discount, sci.settlement_price,
|
|
||||||
sc.contract_code, sc.contract_name, sc.supplier_id,
|
|
||||||
s.supplier_name
|
|
||||||
FROM supply_contract_items sci
|
|
||||||
JOIN supply_contracts sc ON sci.contract_id = sc.id
|
|
||||||
LEFT JOIN suppliers s ON sc.supplier_id = s.id
|
|
||||||
WHERE sci.resellerid = ${resellerid}$
|
|
||||||
AND sc.status = '1'
|
|
||||||
AND sc.start_date <= CURDATE()
|
|
||||||
AND (sc.end_date IS NULL OR sc.end_date >= CURDATE())
|
|
||||||
AND sci.productid = ${productid}$
|
|
||||||
ORDER BY sc.start_date DESC"""
|
|
||||||
recs = await sor.sqlExe(sql, {"resellerid": user_orgid, "productid": productid})
|
|
||||||
|
|
||||||
if not recs and prodtypeid:
|
|
||||||
sql = """SELECT sci.id, sci.contract_id, sci.discount, sci.settlement_price,
|
|
||||||
sc.contract_code, sc.contract_name, sc.supplier_id,
|
|
||||||
s.supplier_name
|
|
||||||
FROM supply_contract_items sci
|
|
||||||
JOIN supply_contracts sc ON sci.contract_id = sc.id
|
|
||||||
LEFT JOIN suppliers s ON sc.supplier_id = s.id
|
|
||||||
WHERE sci.resellerid = ${resellerid}$
|
|
||||||
AND sc.status = '1'
|
|
||||||
AND sc.start_date <= CURDATE()
|
|
||||||
AND (sc.end_date IS NULL OR sc.end_date >= CURDATE())
|
|
||||||
AND sci.prodtypeid = ${prodtypeid}$
|
|
||||||
ORDER BY sc.start_date DESC"""
|
|
||||||
recs = await sor.sqlExe(sql, {"resellerid": user_orgid, "prodtypeid": prodtypeid})
|
|
||||||
|
|
||||||
if not recs:
|
|
||||||
# Fallback to contract default
|
|
||||||
sql = """SELECT id as contract_id, contract_code, contract_name,
|
|
||||||
supplier_id, default_discount as discount, NULL as settlement_price
|
|
||||||
FROM supply_contracts
|
|
||||||
WHERE resellerid = ${resellerid}$
|
|
||||||
AND status = '1'
|
|
||||||
AND start_date <= CURDATE()
|
|
||||||
AND (end_date IS NULL OR end_date >= CURDATE())
|
|
||||||
ORDER BY start_date DESC"""
|
|
||||||
recs = await sor.sqlExe(sql, {"resellerid": user_orgid})
|
|
||||||
|
|
||||||
result = [dict(r) for r in recs] if recs else []
|
|
||||||
return json.dumps({"status": "ok", "data": result})
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
import json
|
|
||||||
from appPublic.uniqueID import getID
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
async def main(request, params_kw):
|
|
||||||
"""Create a new sub_distributors record."""
|
|
||||||
user_id = await get_user()
|
|
||||||
user_orgid = await get_userorgid()
|
|
||||||
dbname = get_module_dbname('supplychain')
|
|
||||||
|
|
||||||
data = params_kw.get("data", "{}")
|
|
||||||
if isinstance(data, str):
|
|
||||||
data = json.loads(data)
|
|
||||||
|
|
||||||
data["id"] = getID()
|
|
||||||
data["resellerid"] = user_orgid
|
|
||||||
data["created_by"] = user_id
|
|
||||||
data["created_at"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
||||||
|
|
||||||
# Auto-generate sub distributor code
|
|
||||||
if not data.get("sub_dist_code"):
|
|
||||||
data["sub_dist_code"] = f"SUB-{datetime.now().strftime('%Y%m%d')}-{getID()[:4].upper()}"
|
|
||||||
|
|
||||||
config = getConfig(".")
|
|
||||||
DBPools(config.databases)
|
|
||||||
async with db.sqlorContext(dbname) as sor:
|
|
||||||
await sor.C("sub_distributors", data)
|
|
||||||
return json.dumps({"status": "ok", "data": data})
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
import json
|
|
||||||
|
|
||||||
async def main(request, params_kw):
|
|
||||||
"""Delete a sub_distributors record."""
|
|
||||||
dbname = get_module_dbname('supplychain')
|
|
||||||
|
|
||||||
data = params_kw.get("data", "{}")
|
|
||||||
if isinstance(data, str):
|
|
||||||
data = json.loads(data)
|
|
||||||
|
|
||||||
record_id = data.get("id")
|
|
||||||
if not record_id:
|
|
||||||
return json.dumps({"status": "error", "message": "Missing record id"})
|
|
||||||
|
|
||||||
config = getConfig(".")
|
|
||||||
DBPools(config.databases)
|
|
||||||
async with db.sqlorContext(dbname) as sor:
|
|
||||||
await sor.D("sub_distributors", {"id": record_id})
|
|
||||||
return json.dumps({"status": "ok", "message": "Deleted successfully"})
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
import json
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
async def main(request, params_kw):
|
|
||||||
"""Update a sub_distributors record."""
|
|
||||||
user_id = await get_user()
|
|
||||||
dbname = get_module_dbname('supplychain')
|
|
||||||
|
|
||||||
data = params_kw.get("data", "{}")
|
|
||||||
if isinstance(data, str):
|
|
||||||
data = json.loads(data)
|
|
||||||
|
|
||||||
record_id = data.get("id")
|
|
||||||
if not record_id:
|
|
||||||
return json.dumps({"status": "error", "message": "Missing record id"})
|
|
||||||
|
|
||||||
data["updated_at"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
||||||
|
|
||||||
# Remove fields that should not be updated
|
|
||||||
for key in ["id", "resellerid", "created_by", "created_at"]:
|
|
||||||
data.pop(key, None)
|
|
||||||
|
|
||||||
config = getConfig(".")
|
|
||||||
DBPools(config.databases)
|
|
||||||
async with db.sqlorContext(dbname) as sor:
|
|
||||||
await sor.U("sub_distributors", data)
|
|
||||||
return json.dumps({"status": "ok", "data": data})
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
import json
|
|
||||||
from appPublic.uniqueID import getID
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
async def main(request, params_kw):
|
|
||||||
"""Create a new suppliers record."""
|
|
||||||
user_id = await get_user()
|
|
||||||
user_orgid = await get_userorgid()
|
|
||||||
dbname = get_module_dbname('supplychain')
|
|
||||||
|
|
||||||
data = params_kw.get("data", "{}")
|
|
||||||
if isinstance(data, str):
|
|
||||||
data = json.loads(data)
|
|
||||||
|
|
||||||
data["id"] = getID()
|
|
||||||
data["resellerid"] = user_orgid
|
|
||||||
data["created_by"] = user_id
|
|
||||||
data["created_at"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
||||||
|
|
||||||
# Auto-generate supplier code
|
|
||||||
if not data.get("supplier_code"):
|
|
||||||
data["supplier_code"] = f"SUP-{datetime.now().strftime('%Y%m%d')}-{getID()[:4].upper()}"
|
|
||||||
|
|
||||||
config = getConfig(".")
|
|
||||||
DBPools(config.databases)
|
|
||||||
async with db.sqlorContext(dbname) as sor:
|
|
||||||
await sor.C("suppliers", data)
|
|
||||||
return json.dumps({"status": "ok", "data": data})
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
import json
|
|
||||||
|
|
||||||
async def main(request, params_kw):
|
|
||||||
"""Delete a suppliers record."""
|
|
||||||
dbname = get_module_dbname('supplychain')
|
|
||||||
|
|
||||||
data = params_kw.get("data", "{}")
|
|
||||||
if isinstance(data, str):
|
|
||||||
data = json.loads(data)
|
|
||||||
|
|
||||||
record_id = data.get("id")
|
|
||||||
if not record_id:
|
|
||||||
return json.dumps({"status": "error", "message": "Missing record id"})
|
|
||||||
|
|
||||||
config = getConfig(".")
|
|
||||||
DBPools(config.databases)
|
|
||||||
async with db.sqlorContext(dbname) as sor:
|
|
||||||
await sor.D("suppliers", {"id": record_id})
|
|
||||||
return json.dumps({"status": "ok", "message": "Deleted successfully"})
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
import json
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
async def main(request, params_kw):
|
|
||||||
"""Update a suppliers record."""
|
|
||||||
user_id = await get_user()
|
|
||||||
dbname = get_module_dbname('supplychain')
|
|
||||||
|
|
||||||
data = params_kw.get("data", "{}")
|
|
||||||
if isinstance(data, str):
|
|
||||||
data = json.loads(data)
|
|
||||||
|
|
||||||
record_id = data.get("id")
|
|
||||||
if not record_id:
|
|
||||||
return json.dumps({"status": "error", "message": "Missing record id"})
|
|
||||||
|
|
||||||
data["updated_at"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
||||||
|
|
||||||
# Remove fields that should not be updated
|
|
||||||
for key in ["id", "resellerid", "created_by", "created_at"]:
|
|
||||||
data.pop(key, None)
|
|
||||||
|
|
||||||
config = getConfig(".")
|
|
||||||
DBPools(config.databases)
|
|
||||||
async with db.sqlorContext(dbname) as sor:
|
|
||||||
await sor.U("suppliers", data)
|
|
||||||
return json.dumps({"status": "ok", "data": data})
|
|
||||||
@ -1,23 +0,0 @@
|
|||||||
import json
|
|
||||||
from appPublic.uniqueID import getID
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
async def main(request, params_kw):
|
|
||||||
"""Create a new supply_contract_items record."""
|
|
||||||
user_id = await get_user()
|
|
||||||
user_orgid = await get_userorgid()
|
|
||||||
dbname = get_module_dbname('supplychain')
|
|
||||||
|
|
||||||
data = params_kw.get("data", "{}")
|
|
||||||
if isinstance(data, str):
|
|
||||||
data = json.loads(data)
|
|
||||||
|
|
||||||
data["id"] = getID()
|
|
||||||
data["resellerid"] = user_orgid
|
|
||||||
data["created_at"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
||||||
|
|
||||||
config = getConfig(".")
|
|
||||||
DBPools(config.databases)
|
|
||||||
async with db.sqlorContext(dbname) as sor:
|
|
||||||
await sor.C("supply_contract_items", data)
|
|
||||||
return json.dumps({"status": "ok", "data": data})
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
import json
|
|
||||||
|
|
||||||
async def main(request, params_kw):
|
|
||||||
"""Delete a supply_contract_items record."""
|
|
||||||
dbname = get_module_dbname('supplychain')
|
|
||||||
|
|
||||||
data = params_kw.get("data", "{}")
|
|
||||||
if isinstance(data, str):
|
|
||||||
data = json.loads(data)
|
|
||||||
|
|
||||||
record_id = data.get("id")
|
|
||||||
if not record_id:
|
|
||||||
return json.dumps({"status": "error", "message": "Missing record id"})
|
|
||||||
|
|
||||||
config = getConfig(".")
|
|
||||||
DBPools(config.databases)
|
|
||||||
async with db.sqlorContext(dbname) as sor:
|
|
||||||
await sor.D("supply_contract_items", {"id": record_id})
|
|
||||||
return json.dumps({"status": "ok", "message": "Deleted successfully"})
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
import json
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
async def main(request, params_kw):
|
|
||||||
"""Update a supply_contract_items record."""
|
|
||||||
user_id = await get_user()
|
|
||||||
dbname = get_module_dbname('supplychain')
|
|
||||||
|
|
||||||
data = params_kw.get("data", "{}")
|
|
||||||
if isinstance(data, str):
|
|
||||||
data = json.loads(data)
|
|
||||||
|
|
||||||
record_id = data.get("id")
|
|
||||||
if not record_id:
|
|
||||||
return json.dumps({"status": "error", "message": "Missing record id"})
|
|
||||||
|
|
||||||
data["updated_at"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
||||||
|
|
||||||
# Remove fields that should not be updated
|
|
||||||
for key in ["id", "resellerid", "created_by", "created_at"]:
|
|
||||||
data.pop(key, None)
|
|
||||||
|
|
||||||
config = getConfig(".")
|
|
||||||
DBPools(config.databases)
|
|
||||||
async with db.sqlorContext(dbname) as sor:
|
|
||||||
await sor.U("supply_contract_items", data)
|
|
||||||
return json.dumps({"status": "ok", "data": data})
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
import json
|
|
||||||
from appPublic.uniqueID import getID
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
async def main(request, params_kw):
|
|
||||||
"""Create a new supply_contracts record."""
|
|
||||||
user_id = await get_user()
|
|
||||||
user_orgid = await get_userorgid()
|
|
||||||
dbname = get_module_dbname('supplychain')
|
|
||||||
|
|
||||||
data = params_kw.get("data", "{}")
|
|
||||||
if isinstance(data, str):
|
|
||||||
data = json.loads(data)
|
|
||||||
|
|
||||||
data["id"] = getID()
|
|
||||||
data["resellerid"] = user_orgid
|
|
||||||
data["created_by"] = user_id
|
|
||||||
data["created_at"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
||||||
|
|
||||||
# Auto-generate contract code
|
|
||||||
if not data.get("contract_code"):
|
|
||||||
data["contract_code"] = f"SC-{datetime.now().strftime('%Y%m%d')}-{getID()[:4].upper()}"
|
|
||||||
|
|
||||||
config = getConfig(".")
|
|
||||||
DBPools(config.databases)
|
|
||||||
async with db.sqlorContext(dbname) as sor:
|
|
||||||
await sor.C("supply_contracts", data)
|
|
||||||
return json.dumps({"status": "ok", "data": data})
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
import json
|
|
||||||
|
|
||||||
async def main(request, params_kw):
|
|
||||||
"""Delete a supply_contracts record."""
|
|
||||||
dbname = get_module_dbname('supplychain')
|
|
||||||
|
|
||||||
data = params_kw.get("data", "{}")
|
|
||||||
if isinstance(data, str):
|
|
||||||
data = json.loads(data)
|
|
||||||
|
|
||||||
record_id = data.get("id")
|
|
||||||
if not record_id:
|
|
||||||
return json.dumps({"status": "error", "message": "Missing record id"})
|
|
||||||
|
|
||||||
config = getConfig(".")
|
|
||||||
DBPools(config.databases)
|
|
||||||
async with db.sqlorContext(dbname) as sor:
|
|
||||||
await sor.D("supply_contracts", {"id": record_id})
|
|
||||||
return json.dumps({"status": "ok", "message": "Deleted successfully"})
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
import json
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
async def main(request, params_kw):
|
|
||||||
"""Update a supply_contracts record."""
|
|
||||||
user_id = await get_user()
|
|
||||||
dbname = get_module_dbname('supplychain')
|
|
||||||
|
|
||||||
data = params_kw.get("data", "{}")
|
|
||||||
if isinstance(data, str):
|
|
||||||
data = json.loads(data)
|
|
||||||
|
|
||||||
record_id = data.get("id")
|
|
||||||
if not record_id:
|
|
||||||
return json.dumps({"status": "error", "message": "Missing record id"})
|
|
||||||
|
|
||||||
data["updated_at"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
||||||
|
|
||||||
# Remove fields that should not be updated
|
|
||||||
for key in ["id", "resellerid", "created_by", "created_at"]:
|
|
||||||
data.pop(key, None)
|
|
||||||
|
|
||||||
config = getConfig(".")
|
|
||||||
DBPools(config.databases)
|
|
||||||
async with db.sqlorContext(dbname) as sor:
|
|
||||||
await sor.U("supply_contracts", data)
|
|
||||||
return json.dumps({"status": "ok", "data": data})
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
import json
|
|
||||||
from appPublic.uniqueID import getID
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
async def main(request, params_kw):
|
|
||||||
"""Create a new supplychain_accounting record."""
|
|
||||||
user_id = await get_user()
|
|
||||||
user_orgid = await get_userorgid()
|
|
||||||
dbname = get_module_dbname('supplychain')
|
|
||||||
|
|
||||||
data = params_kw.get("data", "{}")
|
|
||||||
if isinstance(data, str):
|
|
||||||
data = json.loads(data)
|
|
||||||
|
|
||||||
data["id"] = getID()
|
|
||||||
data["resellerid"] = user_orgid
|
|
||||||
data["created_by"] = user_id
|
|
||||||
data["created_at"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
||||||
|
|
||||||
config = getConfig(".")
|
|
||||||
DBPools(config.databases)
|
|
||||||
async with db.sqlorContext(dbname) as sor:
|
|
||||||
await sor.C("supplychain_accounting", data)
|
|
||||||
return json.dumps({"status": "ok", "data": data})
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
import json
|
|
||||||
|
|
||||||
async def main(request, params_kw):
|
|
||||||
"""Delete a supplychain_accounting record."""
|
|
||||||
dbname = get_module_dbname('supplychain')
|
|
||||||
|
|
||||||
data = params_kw.get("data", "{}")
|
|
||||||
if isinstance(data, str):
|
|
||||||
data = json.loads(data)
|
|
||||||
|
|
||||||
record_id = data.get("id")
|
|
||||||
if not record_id:
|
|
||||||
return json.dumps({"status": "error", "message": "Missing record id"})
|
|
||||||
|
|
||||||
config = getConfig(".")
|
|
||||||
DBPools(config.databases)
|
|
||||||
async with db.sqlorContext(dbname) as sor:
|
|
||||||
await sor.D("supplychain_accounting", {"id": record_id})
|
|
||||||
return json.dumps({"status": "ok", "message": "Deleted successfully"})
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
import json
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
async def main(request, params_kw):
|
|
||||||
"""Update a supplychain_accounting record."""
|
|
||||||
user_id = await get_user()
|
|
||||||
dbname = get_module_dbname('supplychain')
|
|
||||||
|
|
||||||
data = params_kw.get("data", "{}")
|
|
||||||
if isinstance(data, str):
|
|
||||||
data = json.loads(data)
|
|
||||||
|
|
||||||
record_id = data.get("id")
|
|
||||||
if not record_id:
|
|
||||||
return json.dumps({"status": "error", "message": "Missing record id"})
|
|
||||||
|
|
||||||
data["updated_at"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
||||||
|
|
||||||
# Remove fields that should not be updated
|
|
||||||
for key in ["id", "resellerid", "created_by", "created_at"]:
|
|
||||||
data.pop(key, None)
|
|
||||||
|
|
||||||
config = getConfig(".")
|
|
||||||
DBPools(config.databases)
|
|
||||||
async with db.sqlorContext(dbname) as sor:
|
|
||||||
await sor.U("supplychain_accounting", data)
|
|
||||||
return json.dumps({"status": "ok", "data": data})
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
{
|
|
||||||
"widgettype": "VBox",
|
|
||||||
"options": {
|
|
||||||
"width": "100%",
|
|
||||||
"height": "100%",
|
|
||||||
"padding": "16px"
|
|
||||||
},
|
|
||||||
"subwidgets": [
|
|
||||||
{
|
|
||||||
"widgettype": "Text",
|
|
||||||
"options": {
|
|
||||||
"text": "分销协议管理",
|
|
||||||
"fontSize": "20px",
|
|
||||||
"fontWeight": "bold",
|
|
||||||
"marginBottom": "16px"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"widgettype": "DataViewer",
|
|
||||||
"options": {
|
|
||||||
"url": "{{entire_url('distribution_agreements_list/index.ui')}}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
163
wwwroot/index.ui
163
wwwroot/index.ui
@ -1,163 +0,0 @@
|
|||||||
{
|
|
||||||
"widgettype": "VBox",
|
|
||||||
"options": {
|
|
||||||
"width": "100%",
|
|
||||||
"height": "100%",
|
|
||||||
"padding": "20px",
|
|
||||||
"bgcolor": "#F5F5F5"
|
|
||||||
},
|
|
||||||
"subwidgets": [
|
|
||||||
{
|
|
||||||
"widgettype": "Text",
|
|
||||||
"options": {
|
|
||||||
"text": "供销链管理",
|
|
||||||
"fontSize": "24px",
|
|
||||||
"fontWeight": "bold",
|
|
||||||
"color": "#333333",
|
|
||||||
"marginBottom": "20px"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"widgettype": "Text",
|
|
||||||
"options": {
|
|
||||||
"text": "供应商、合同、二级分销商、分销协议及供销记账",
|
|
||||||
"fontSize": "14px",
|
|
||||||
"color": "#666666",
|
|
||||||
"marginBottom": "24px"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"widgettype": "ResponsableBox",
|
|
||||||
"options": {
|
|
||||||
"gap": "16px",
|
|
||||||
"minWidth": "250px"
|
|
||||||
},
|
|
||||||
"subwidgets": [
|
|
||||||
{
|
|
||||||
"widgettype": "VBox",
|
|
||||||
"options": {
|
|
||||||
"bgcolor": "#FFFFFF",
|
|
||||||
"padding": "20px",
|
|
||||||
"borderRadius": "8px",
|
|
||||||
"cursor": "pointer",
|
|
||||||
"boxShadow": "0 2px 4px rgba(0,0,0,0.1)"
|
|
||||||
},
|
|
||||||
"binds": [{
|
|
||||||
"wid": "self",
|
|
||||||
"event": "click",
|
|
||||||
"actiontype": "urlwidget",
|
|
||||||
"target": "app.supplychain_content",
|
|
||||||
"options": {"url": "{{entire_url('suppliers.ui')}}"},
|
|
||||||
"mode": "replace"
|
|
||||||
}],
|
|
||||||
"subwidgets": [
|
|
||||||
{"widgettype": "Text", "options": {"text": "🏭", "fontSize": "32px", "textAlign": "center"}},
|
|
||||||
{"widgettype": "Text", "options": {"text": "供应商管理", "fontSize": "16px", "fontWeight": "bold", "textAlign": "center", "marginTop": "8px"}},
|
|
||||||
{"widgettype": "Text", "options": {"text": "添加和管理供应商信息", "fontSize": "12px", "color": "#999999", "textAlign": "center"}}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"widgettype": "VBox",
|
|
||||||
"options": {
|
|
||||||
"bgcolor": "#FFFFFF",
|
|
||||||
"padding": "20px",
|
|
||||||
"borderRadius": "8px",
|
|
||||||
"cursor": "pointer",
|
|
||||||
"boxShadow": "0 2px 4px rgba(0,0,0,0.1)"
|
|
||||||
},
|
|
||||||
"binds": [{
|
|
||||||
"wid": "self",
|
|
||||||
"event": "click",
|
|
||||||
"actiontype": "urlwidget",
|
|
||||||
"target": "app.supplychain_content",
|
|
||||||
"options": {"url": "{{entire_url('supply_contracts.ui')}}"},
|
|
||||||
"mode": "replace"
|
|
||||||
}],
|
|
||||||
"subwidgets": [
|
|
||||||
{"widgettype": "Text", "options": {"text": "📋", "fontSize": "32px", "textAlign": "center"}},
|
|
||||||
{"widgettype": "Text", "options": {"text": "供销合同", "fontSize": "16px", "fontWeight": "bold", "textAlign": "center", "marginTop": "8px"}},
|
|
||||||
{"widgettype": "Text", "options": {"text": "管理与供应商的供销合同及产品折扣", "fontSize": "12px", "color": "#999999", "textAlign": "center"}}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"widgettype": "VBox",
|
|
||||||
"options": {
|
|
||||||
"bgcolor": "#FFFFFF",
|
|
||||||
"padding": "20px",
|
|
||||||
"borderRadius": "8px",
|
|
||||||
"cursor": "pointer",
|
|
||||||
"boxShadow": "0 2px 4px rgba(0,0,0,0.1)"
|
|
||||||
},
|
|
||||||
"binds": [{
|
|
||||||
"wid": "self",
|
|
||||||
"event": "click",
|
|
||||||
"actiontype": "urlwidget",
|
|
||||||
"target": "app.supplychain_content",
|
|
||||||
"options": {"url": "{{entire_url('sub_distributors.ui')}}"},
|
|
||||||
"mode": "replace"
|
|
||||||
}],
|
|
||||||
"subwidgets": [
|
|
||||||
{"widgettype": "Text", "options": {"text": "🏪", "fontSize": "32px", "textAlign": "center"}},
|
|
||||||
{"widgettype": "Text", "options": {"text": "二级分销商", "fontSize": "16px", "fontWeight": "bold", "textAlign": "center", "marginTop": "8px"}},
|
|
||||||
{"widgettype": "Text", "options": {"text": "添加和管理二级分销商", "fontSize": "12px", "color": "#999999", "textAlign": "center"}}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"widgettype": "VBox",
|
|
||||||
"options": {
|
|
||||||
"bgcolor": "#FFFFFF",
|
|
||||||
"padding": "20px",
|
|
||||||
"borderRadius": "8px",
|
|
||||||
"cursor": "pointer",
|
|
||||||
"boxShadow": "0 2px 4px rgba(0,0,0,0.1)"
|
|
||||||
},
|
|
||||||
"binds": [{
|
|
||||||
"wid": "self",
|
|
||||||
"event": "click",
|
|
||||||
"actiontype": "urlwidget",
|
|
||||||
"target": "app.supplychain_content",
|
|
||||||
"options": {"url": "{{entire_url('distribution_agreements.ui')}}"},
|
|
||||||
"mode": "replace"
|
|
||||||
}],
|
|
||||||
"subwidgets": [
|
|
||||||
{"widgettype": "Text", "options": {"text": "📝", "fontSize": "32px", "textAlign": "center"}},
|
|
||||||
{"widgettype": "Text", "options": {"text": "分销协议", "fontSize": "16px", "fontWeight": "bold", "textAlign": "center", "marginTop": "8px"}},
|
|
||||||
{"widgettype": "Text", "options": {"text": "管理与二级分销商的分销协议及产品折扣", "fontSize": "12px", "color": "#999999", "textAlign": "center"}}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"widgettype": "VBox",
|
|
||||||
"options": {
|
|
||||||
"bgcolor": "#FFFFFF",
|
|
||||||
"padding": "20px",
|
|
||||||
"borderRadius": "8px",
|
|
||||||
"cursor": "pointer",
|
|
||||||
"boxShadow": "0 2px 4px rgba(0,0,0,0.1)"
|
|
||||||
},
|
|
||||||
"binds": [{
|
|
||||||
"wid": "self",
|
|
||||||
"event": "click",
|
|
||||||
"actiontype": "urlwidget",
|
|
||||||
"target": "app.supplychain_content",
|
|
||||||
"options": {"url": "{{entire_url('accounting.ui')}}"},
|
|
||||||
"mode": "replace"
|
|
||||||
}],
|
|
||||||
"subwidgets": [
|
|
||||||
{"widgettype": "Text", "options": {"text": "💰", "fontSize": "32px", "textAlign": "center"}},
|
|
||||||
{"widgettype": "Text", "options": {"text": "供销记账", "fontSize": "16px", "fontWeight": "bold", "textAlign": "center", "marginTop": "8px"}},
|
|
||||||
{"widgettype": "Text", "options": {"text": "查看供销关系记账记录和利润统计", "fontSize": "12px", "color": "#999999", "textAlign": "center"}}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"widgettype": "VBox",
|
|
||||||
"id": "supplychain_content",
|
|
||||||
"options": {
|
|
||||||
"width": "100%",
|
|
||||||
"flex": "1",
|
|
||||||
"marginTop": "20px"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
{
|
|
||||||
"widgettype": "Menu",
|
|
||||||
"options": {
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "供应商管理",
|
|
||||||
"url": "{{entire_url('suppliers.ui')}}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "供销合同",
|
|
||||||
"url": "{{entire_url('supply_contracts.ui')}}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "二级分销商",
|
|
||||||
"url": "{{entire_url('sub_distributors.ui')}}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "分销协议",
|
|
||||||
"url": "{{entire_url('distribution_agreements.ui')}}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "供销记账",
|
|
||||||
"url": "{{entire_url('accounting.ui')}}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
{
|
|
||||||
"widgettype": "VBox",
|
|
||||||
"options": {
|
|
||||||
"width": "100%",
|
|
||||||
"height": "100%",
|
|
||||||
"padding": "16px"
|
|
||||||
},
|
|
||||||
"subwidgets": [
|
|
||||||
{
|
|
||||||
"widgettype": "Text",
|
|
||||||
"options": {
|
|
||||||
"text": "二级分销商管理",
|
|
||||||
"fontSize": "20px",
|
|
||||||
"fontWeight": "bold",
|
|
||||||
"marginBottom": "16px"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"widgettype": "DataViewer",
|
|
||||||
"options": {
|
|
||||||
"url": "{{entire_url('sub_distributors_list/index.ui')}}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
{
|
|
||||||
"widgettype": "VBox",
|
|
||||||
"options": {
|
|
||||||
"width": "100%",
|
|
||||||
"height": "100%",
|
|
||||||
"padding": "16px"
|
|
||||||
},
|
|
||||||
"subwidgets": [
|
|
||||||
{
|
|
||||||
"widgettype": "Text",
|
|
||||||
"options": {
|
|
||||||
"text": "供应商管理",
|
|
||||||
"fontSize": "20px",
|
|
||||||
"fontWeight": "bold",
|
|
||||||
"marginBottom": "16px"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"widgettype": "DataViewer",
|
|
||||||
"options": {
|
|
||||||
"url": "{{entire_url('suppliers_list/index.ui')}}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
{
|
|
||||||
"widgettype": "VBox",
|
|
||||||
"options": {
|
|
||||||
"width": "100%",
|
|
||||||
"height": "100%",
|
|
||||||
"padding": "16px"
|
|
||||||
},
|
|
||||||
"subwidgets": [
|
|
||||||
{
|
|
||||||
"widgettype": "Text",
|
|
||||||
"options": {
|
|
||||||
"text": "供销合同管理",
|
|
||||||
"fontSize": "20px",
|
|
||||||
"fontWeight": "bold",
|
|
||||||
"marginBottom": "16px"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"widgettype": "DataViewer",
|
|
||||||
"options": {
|
|
||||||
"url": "{{entire_url('supply_contracts_list/index.ui')}}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user