92 lines
1.8 KiB
Go
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
|
|
}
|
|
}
|