Files
2026-07-31 10:31:17 +08:00

92 lines
1.8 KiB
Go

package applogic
import (
"fmt"
"strconv"
"aijianzhan/platform/internal/authx"
"aijianzhan/platform/internal/types"
)
func (l *CrudLogic) Aggregate(slug, resource, groupBy, sumField string) (*types.AggregateResp, error) {
tenantID := authx.TenantID(l.ctx)
ref, err := l.svcCtx.Meta.ResolveResource(l.ctx, tenantID, slug, resource)
if err != nil {
return nil, err
}
if groupBy != "" {
ok := false
if ref.Resource.List != nil {
for _, f := range ref.Resource.List.AllowedFilters {
if f == groupBy {
ok = true
break
}
}
}
for _, f := range ref.Entity.Fields {
if f.Name == groupBy {
ok = true
break
}
}
if !ok {
return nil, fmt.Errorf("group_by not allowed: %s", groupBy)
}
}
items, total, err := l.svcCtx.CRUD.List(l.ctx, ref, tenantID, 1, 5000, nil, "")
if err != nil {
return nil, err
}
resp := &types.AggregateResp{Total: total, GroupBy: groupBy, SumField: sumField}
if groupBy == "" {
if sumField != "" {
for _, it := range items {
resp.Sum += toFloat(it[sumField])
}
}
return resp, nil
}
buckets := map[string]*types.AggregateBucket{}
order := []string{}
for _, it := range items {
key := fmt.Sprint(it[groupBy])
if key == "" || key == "<nil>" {
key = "(空)"
}
b, ok := buckets[key]
if !ok {
b = &types.AggregateBucket{Key: key}
buckets[key] = b
order = append(order, key)
}
b.Count++
if sumField != "" {
b.Sum += toFloat(it[sumField])
resp.Sum += toFloat(it[sumField])
}
}
for _, k := range order {
resp.Buckets = append(resp.Buckets, *buckets[k])
}
return resp, nil
}
func toFloat(v any) float64 {
switch t := v.(type) {
case float64:
return t
case float32:
return float64(t)
case int:
return float64(t)
case int64:
return float64(t)
case string:
n, _ := strconv.ParseFloat(t, 64)
return n
default:
return 0
}
}