From d1b30deb4aaf7b47c88aa5e92e201bf87f136543 Mon Sep 17 00:00:00 2001 From: zhouyonggao <1971162852@qq.com> Date: Wed, 17 Dec 2025 17:39:35 +0800 Subject: [PATCH] =?UTF-8?q?feat(export):=20=E5=A2=9E=E5=BC=BASQL=E6=9E=84?= =?UTF-8?q?=E5=BB=BA=E9=80=BB=E8=BE=91=E4=BB=A5=E6=94=AF=E6=8C=81YMT?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=BA=90=E7=9A=84ID=E8=BF=87=E6=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在BuildSQL函数中添加对reseller_id_eq和merchant_id_eq的处理逻辑,确保在YMT数据源下有效过滤无效ID - 更新去重逻辑以支持YMT数据源的特定需求,提升SQL构建的灵活性 - 优化聚合查询时的字段别名处理,确保主表字段正确引用 - 增强代码可读性,确保逻辑清晰明了 --- server/internal/exporter/sqlbuilder.go | 78 ++++++++++++++++++++++---- 1 file changed, 68 insertions(+), 10 deletions(-) diff --git a/server/internal/exporter/sqlbuilder.go b/server/internal/exporter/sqlbuilder.go index 3850f49..5fb01d7 100644 --- a/server/internal/exporter/sqlbuilder.go +++ b/server/internal/exporter/sqlbuilder.go @@ -245,6 +245,19 @@ func BuildSQL(req BuildRequest, whitelist map[string]bool) (string, []interface{ delete(req.Filters, "merchant_id_eq") } } + // normalize reseller_id_eq (YMT 直连 merchant_id) + if req.Datasource == "ymt" && (req.MainTable == "order" || req.MainTable == "order_info") { + if v, ok := req.Filters["reseller_id_eq"]; ok { + if isZeroID(v) { + delete(req.Filters, "reseller_id_eq") + } else { + if _, has := req.Filters["merchant_id_in"]; !has { + req.Filters["merchant_id_in"] = []interface{}{v} + } + delete(req.Filters, "reseller_id_eq") + } + } + } // helper: treat "0"/0/空 as未提供的 ID isZeroID := func(v interface{}) bool { @@ -520,7 +533,13 @@ func BuildSQL(req BuildRequest, whitelist map[string]bool) (string, []interface{ sb.WriteString(" WHERE ") sb.WriteString(strings.Join(where, " AND ")) } - needDedupe := req.Datasource == "marketing" && req.MainTable == "order" && (need["order_voucher"] || need["voucher"] || need["voucher_batch"] || need["key_batch"] || need["code_batch"]) + needDedupe := false + if req.Datasource == "marketing" && req.MainTable == "order" && (need["order_voucher"] || need["voucher"] || need["voucher_batch"] || need["key_batch"] || need["code_batch"]) { + needDedupe = true + } + if req.Datasource == "ymt" && (req.MainTable == "order" || req.MainTable == "order_info") && (need["order_digit"] || need["order_voucher"] || need["voucher"] || need["voucher_batch"]) { + needDedupe = true + } if needDedupe { // Extract alias names in order aliases := make([]string, 0, len(cols)) @@ -545,8 +564,8 @@ func BuildSQL(req BuildRequest, whitelist map[string]bool) (string, []interface{ } sources = append(sources, src) } - mt := sch.TableName(req.MainTable) - pkCol, _ := sch.MapField(req.MainTable, "order_number") + // 聚合时按别名分组:主表字段别名始终是 req.MainTable.order_number + pkAlias := req.MainTable + ".order_number" var out strings.Builder out.WriteString("SELECT ") for i := range aliases { @@ -563,7 +582,7 @@ func BuildSQL(req BuildRequest, whitelist map[string]bool) (string, []interface{ } out.WriteString(" FROM (") out.WriteString(sb.String()) - out.WriteString(") AS sub GROUP BY sub.`" + mt + "." + pkCol + "`") + out.WriteString(") AS sub GROUP BY sub.`" + pkAlias + "`") return out.String(), args, nil } return sb.String(), args, nil @@ -596,20 +615,51 @@ func BuildCountSQL(req BuildRequest, whitelist map[string]bool) (string, []inter need[tbl] = true } } + // normalize merchant_id_eq / reseller_id_eq for YMT: skip 0/空, 非零转为 merchant_id_in 以便与 creator_in 做 OR + if v, ok := req.Filters["merchant_id_eq"]; ok { + if isZeroID(v) { + delete(req.Filters, "merchant_id_eq") + } else { + if _, has := req.Filters["merchant_id_in"]; !has { + req.Filters["merchant_id_in"] = []interface{}{v} + } + delete(req.Filters, "merchant_id_eq") + } + } + if req.Datasource == "ymt" && (req.MainTable == "order" || req.MainTable == "order_info") { + if v, ok := req.Filters["reseller_id_eq"]; ok { + if isZeroID(v) { + delete(req.Filters, "reseller_id_eq") + } else { + if _, has := req.Filters["merchant_id_in"]; !has { + req.Filters["merchant_id_in"] = []interface{}{v} + } + delete(req.Filters, "reseller_id_eq") + } + } + } // Handle creator_in and merchant_id_in with OR logic if both exist var creatorArgs []interface{} hasCreator := false if v, ok := req.Filters["creator_in"]; ok { switch t := v.(type) { case []interface{}: - creatorArgs = t + for _, x := range t { + if !isZeroID(x) { + creatorArgs = append(creatorArgs, x) + } + } case []int: for _, x := range t { - creatorArgs = append(creatorArgs, x) + if !isZeroID(x) { + creatorArgs = append(creatorArgs, x) + } } case []string: for _, x := range t { - creatorArgs = append(creatorArgs, x) + if !isZeroID(x) { + creatorArgs = append(creatorArgs, x) + } } } if len(creatorArgs) > 0 { @@ -622,14 +672,22 @@ func BuildCountSQL(req BuildRequest, whitelist map[string]bool) (string, []inter if v, ok := req.Filters["merchant_id_in"]; ok { switch t := v.(type) { case []interface{}: - merchantArgs = t + for _, x := range t { + if !isZeroID(x) { + merchantArgs = append(merchantArgs, x) + } + } case []int: for _, x := range t { - merchantArgs = append(merchantArgs, x) + if !isZeroID(x) { + merchantArgs = append(merchantArgs, x) + } } case []string: for _, x := range t { - merchantArgs = append(merchantArgs, x) + if !isZeroID(x) { + merchantArgs = append(merchantArgs, x) + } } } if len(merchantArgs) > 0 {