修复个人中心问题

This commit is contained in:
2026-09-29 18:25:09 +08:00
parent 0dc5c2f075
commit ca4220f92c
44 changed files with 1793 additions and 310 deletions
+16 -61
View File
@@ -121,8 +121,9 @@ func (c *BackendCrmContractController) List() {
cond = cond.And("project_id", pid)
}
}
// 周期筛选:与顶部统计同口径(合同有效期 [生效日期, 结束日期] 与所选周期重叠),
// period=month/quarter/year 取当期区间,period=custom 用 start_date / end_date
// 周期筛选:按「签订日期」归类(与顶部统计同口径)——签订日期落在所选周期内即命中。
// period=month/quarter/year 取当期区间,period=custom 用 start_date / end_date;
// 签订日期为空的合同(草稿 / 尚未填写)不受周期限制,避免默认「本年」时被隐藏。
period := strings.TrimSpace(c.GetString("period"))
rangeStart := strings.TrimSpace(c.GetString("start_date"))
rangeEnd := strings.TrimSpace(c.GetString("end_date"))
@@ -130,67 +131,21 @@ func (c *BackendCrmContractController) List() {
rangeStart, rangeEnd = periodRange(period)
}
if rangeStart != "" {
cond = cond.AndCond(orm.NewCondition().Or("expire_date__isnull", true).Or("expire_date__gte", rangeStart))
cond = cond.AndCond(orm.NewCondition().Or("sign_date__isnull", true).Or("sign_date__gte", rangeStart))
}
if rangeEnd != "" {
cond = cond.AndCond(orm.NewCondition().Or("effective_date__isnull", true).Or("effective_date__lte", rangeEnd))
cond = cond.AndCond(orm.NewCondition().Or("sign_date__isnull", true).Or("sign_date__lte", rangeEnd))
}
qs := models.Orm.QueryTable(new(models.TenantCrmContract)).SetCond(cond)
total, _ := qs.Count()
var list []models.TenantCrmContract
if total > 0 {
offset := (page - 1) * pageSize
if status != "" {
// 已按状态筛选:结果只含单一状态,直接按新→旧分页
if _, err := qs.OrderBy("-id").Offset(offset).Limit(pageSize).All(&list); err != nil {
pipelineErr(&c.Controller, 500, 500, "查询失败: "+err.Error())
return
}
} else {
// 列表排列:按状态分组展示 —— 草稿(1) → 异常(5) → 履约中(4) → 已完成(2) → 已作废(3),
// 其余状态(NULL / 历史异常值)沉底;组内仍按新→旧。
// 先统计各组数量,把当前页窗口换算成各组区间,再分别取数按序拼接,保证翻页后整体顺序一致。
groupConds := []*orm.Condition{
orm.NewCondition().And("status", 1),
orm.NewCondition().And("status", 5),
orm.NewCondition().And("status", 4),
orm.NewCondition().And("status", 2),
orm.NewCondition().And("status", 3),
orm.NewCondition().AndNot("status__in", []int8{1, 5, 4, 2, 3}).Or("status__isnull", true),
}
end := offset + pageSize
if end > int(total) {
end = int(total)
}
cursor := 0
for _, gc := range groupConds {
if cursor >= end {
break
}
// 注意:beego 的 AndCond 会修改接收者,这里用新条件对象包装,避免循环内条件累积
groupCond := orm.NewCondition().AndCond(cond).AndCond(gc)
cnt, _ := models.Orm.QueryTable(new(models.TenantCrmContract)).SetCond(groupCond).Count()
groupTotal := int(cnt)
if groupTotal == 0 {
continue
}
groupStart := cursor
groupEnd := cursor + groupTotal
cursor = groupEnd
// 当前页与本组区间的交集
from, to := max(offset, groupStart), min(end, groupEnd)
if to <= from {
continue
}
var part []models.TenantCrmContract
if _, err := models.Orm.QueryTable(new(models.TenantCrmContract)).SetCond(groupCond).
OrderBy("-id").Offset(from - groupStart).Limit(to - from).All(&part); err != nil {
pipelineErr(&c.Controller, 500, 500, "查询失败: "+err.Error())
return
}
list = append(list, part...)
}
// 列表排列:按「签订日期」倒序,最新签约的合同排最前。
// 同日签约多份时按 id 倒序,保证翻页顺序稳定;签订日期为空的合同(草稿 / 尚未签约)沉底。
if _, err := qs.OrderBy("-sign_date", "-id").Offset((page - 1) * pageSize).Limit(pageSize).All(&list); err != nil {
pipelineErr(&c.Controller, 500, 500, "查询失败: "+err.Error())
return
}
}
// 回款逾期日期(取最早,未收齐且已过计划回款日期):合同「逾期」标签与结束日期口径一并参考
@@ -216,7 +171,7 @@ func (c *BackendCrmContractController) List() {
// Stats GET /backend/crm/contract/stats
// 全租户合同统计(排除已作废),供列表页顶部汇总卡片使用。
// 支持按周期筛选:period=month/quarter/year(当期)或 custom(start_date~end_date),
// 按合同有效期 [生效日期, 结束日期] 与所选周期重叠统计。
// 按合同「签订日期」落在所选周期内统计(与列表口径一致)。
// 「合同总利润」仅统计非甲方(收款方)合同:我方为甲方的合同是采购付款,只有支出、不存在利润。
func (c *BackendCrmContractController) Stats() {
claims, err := pipelineClaims(&c.Controller)
@@ -236,14 +191,14 @@ func (c *BackendCrmContractController) Stats() {
// 我方不参与的合同(our_role=0,如上中游项目的链条合同)不属于我方经营合同,不计入经营统计
where := "tenant_id = ? AND delete_time IS NULL AND status <> 3 AND our_role <> 0"
args := []interface{}{tenantID}
// 按合同有效期 [生效日期, 结束日期] 与所选周期 [start, end] 重叠来统计:
// 合同生效日 <= 周期末 且 合同结束日 >= 周期初;日期为空视为不限制对应边界。
// 按「签订日期」落在所选周期 [start, end] 内统计(与列表口径一致):
// 签订日期为空的合同不受周期限制,视为不限制对应边界。
if start != "" {
where += " AND (expire_date IS NULL OR expire_date >= ?)"
where += " AND (sign_date IS NULL OR sign_date >= ?)"
args = append(args, start)
}
if end != "" {
where += " AND (effective_date IS NULL OR effective_date <= ?)"
where += " AND (sign_date IS NULL OR sign_date <= ?)"
args = append(args, end)
}
// 「合同总利润」只汇总非甲方(收款方)合同:我方为甲方时是采购付款方,合同金额即支出,不存在利润
@@ -268,7 +223,7 @@ func (c *BackendCrmContractController) Stats() {
}
// periodRange 根据 period 返回当期区间 [start, end](YYYY-MM-DD):month/quarter/year。
// 统计与列表均以该区间与合同有效期比较(有效期与周期重叠即命中)。
// 统计与列表均以该区间与合同「签订日期」比较(签订日期落在区间内即命中)。
func periodRange(period string) (string, string) {
now := time.Now()
loc := now.Location()