优化回款功能
This commit is contained in:
@@ -531,7 +531,8 @@ func contractStatusName(s int8) string {
|
||||
|
||||
// ========================== 内部辅助 ==========================
|
||||
|
||||
// buildContractResp 组装响应:parties / products 透传 JSON 数组,summary 由金额字段组装。
|
||||
// buildContractResp 组装响应:parties / products 透传 JSON 数组;
|
||||
// 金额字段在返回前按 products 以当前口径重算(单价含税、不再叠加税率),summary 随之组装。
|
||||
func buildContractResp(row *models.TenantCrmContract) contractResp {
|
||||
parties := json.RawMessage("[]")
|
||||
if strings.TrimSpace(row.Parties) != "" {
|
||||
@@ -541,6 +542,11 @@ func buildContractResp(row *models.TenantCrmContract) contractResp {
|
||||
if strings.TrimSpace(row.Products) != "" {
|
||||
products = json.RawMessage(row.Products)
|
||||
}
|
||||
// 返回前按「单价含税、不再叠加税率」的口径重算金额,
|
||||
// 保证列表/详情与产品清单一致,并自动修正历史数据按旧口径(叠加税率)存的金额
|
||||
if strings.TrimSpace(row.Products) != "" && string(products) != "[]" {
|
||||
applyContractAmounts(row)
|
||||
}
|
||||
return contractResp{
|
||||
TenantCrmContract: *row,
|
||||
Parties: parties,
|
||||
@@ -584,9 +590,9 @@ func normalizeContractJSON(raw json.RawMessage) (string, error) {
|
||||
}
|
||||
|
||||
// applyContractAmounts 按产品清单重算各部分金额(与前端 ProductList 汇总口径一致):
|
||||
// 每行含税金额=数量×单价×(1+税率/100);
|
||||
// 硬件部分=Σ硬件含税小计;软件部分=Σ软件含税小计;其他部分=Σ服务/开发/其他含税小计;
|
||||
// 合同总金额(含税)=硬件+软件+其他;产品总成本=Σ(数量×成本单价)(成本通常不含税,原值汇总);
|
||||
// 清单单价为含税价,每行小计=数量×单价(不再叠加税率,税率仅作开票记录);
|
||||
// 硬件部分=Σ硬件小计;软件部分=Σ软件小计;其他部分=Σ服务/开发/其他小计;
|
||||
// 合同总金额=硬件+软件+其他;产品总成本=Σ(数量×成本单价)(成本为不含税原值);
|
||||
// 合同总利润=总金额-总成本。
|
||||
// 归类口径:分类代码 1/2 或名称含「硬件」/「软件」分别计入硬件/软件,其余计入其他。
|
||||
// contractTreeSellTotal 软件开发模块树售价合计:子节点汇总,叶子=人天×统一人天单价。
|
||||
@@ -642,8 +648,8 @@ func applyContractAmounts(row *models.TenantCrmContract) {
|
||||
qty := toFloat64(item["quantity"])
|
||||
price := toFloat64(item["price"])
|
||||
costPrice := toFloat64(item["cost_price"])
|
||||
taxRate := toFloat64(item["tax_rate"])
|
||||
amount := round2(qty * price * (1 + taxRate/100)) // 含税金额
|
||||
// 清单单价为含税价:小计 = 数量 × 单价,不再叠加税率(税率仅作开票记录,不参与金额计算)
|
||||
amount := round2(qty * price)
|
||||
cost = round2(cost + round2(qty*costPrice))
|
||||
cat := fmt.Sprintf("%v", item["category"])
|
||||
switch {
|
||||
|
||||
Reference in New Issue
Block a user