From 741722b6b18c7a3bc2395087aeb7ba42283e9a32 Mon Sep 17 00:00:00 2001 From: zhouyonggao <1971162852@qq.com> Date: Wed, 26 Nov 2025 18:16:01 +0800 Subject: [PATCH] =?UTF-8?q?feat(exporter):=20=E6=94=AF=E6=8C=81=E4=BB=8Eor?= =?UTF-8?q?der=5Finfo=E8=A1=A8=E5=AF=BC=E5=87=BA=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=B9=B6=E9=80=82=E9=85=8D=E4=B8=8D=E5=90=8C=E8=A1=A8=E7=BB=93?= =?UTF-8?q?=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修改SQL构建逻辑以同时支持从order和order_info表导出数据 根据主表类型自动适配不同的字段名和关联条件 --- server/internal/exporter/sqlbuilder.go | 317 +++++++++++++++---------- server/log/server-20251126.log | 5 + 2 files changed, 192 insertions(+), 130 deletions(-) diff --git a/server/internal/exporter/sqlbuilder.go b/server/internal/exporter/sqlbuilder.go index 6ab8654..237c633 100644 --- a/server/internal/exporter/sqlbuilder.go +++ b/server/internal/exporter/sqlbuilder.go @@ -14,9 +14,9 @@ type BuildRequest struct { } func BuildSQL(req BuildRequest, whitelist map[string]bool) (string, []interface{}, error) { - if req.MainTable != "order" { - return "", nil, errors.New("unsupported main table") - } + if req.MainTable != "order" && req.MainTable != "order_info" { + return "", nil, errors.New("unsupported main table") + } cols := []string{} need := map[string]bool{} for _, tf := range req.Fields { @@ -71,44 +71,49 @@ func BuildSQL(req BuildRequest, whitelist map[string]bool) (string, []interface{ sb := strings.Builder{} sb.WriteString("SELECT ") sb.WriteString(strings.Join(cols, ",")) - sb.WriteString(" FROM `order`") + sb.WriteString(" FROM `" + req.MainTable + "`") // JOINs based on need // order_detail - if need["order_detail"] { - sb.WriteString(" LEFT JOIN `order_detail` ON `order_detail`.order_number = `order`.order_number") - } - // order_cash - if need["order_cash"] { - sb.WriteString(" LEFT JOIN `order_cash` ON `order_cash`.order_number = `order`.order_number") - } - // order_voucher - if need["order_voucher"] { - sb.WriteString(" LEFT JOIN `order_voucher` ON `order_voucher`.order_number = `order`.order_number") - } + if need["order_detail"] && req.MainTable == "order" { + sb.WriteString(" LEFT JOIN `order_detail` ON `order_detail`.order_number = `order`.order_number") + } + // order_cash + if need["order_cash"] { + if req.MainTable == "order_info" { + sb.WriteString(" LEFT JOIN `order_cash` ON `order_cash`.order_no = `order_info`.order_no") + } else { + sb.WriteString(" LEFT JOIN `order_cash` ON `order_cash`.order_number = `order`.order_number") + } + } + // order_voucher + if need["order_voucher"] { + if req.MainTable == "order_info" { + sb.WriteString(" LEFT JOIN `order_voucher` ON `order_voucher`.order_no = `order_info`.order_no") + } else { + sb.WriteString(" LEFT JOIN `order_voucher` ON `order_voucher`.order_number = `order`.order_number") + } + } // plan - if need["plan"] || need["key_batch"] { - sb.WriteString(" LEFT JOIN `plan` ON `plan`.id = `order`.plan_id") - } - // key_batch depends on plan - if need["key_batch"] { - sb.WriteString(" LEFT JOIN `key_batch` ON `key_batch`.plan_id = `plan`.id") - } - // code_batch depends on key_batch - if need["code_batch"] { - sb.WriteString(" LEFT JOIN `code_batch` ON `code_batch`.key_batch_id = `key_batch`.id") - } - // voucher depends on order_voucher - if need["voucher"] { - sb.WriteString(" LEFT JOIN `voucher` ON `voucher`.channel_activity_id = `order_voucher`.channel_activity_id") - } - // voucher_batch depends on voucher - if need["voucher_batch"] { - sb.WriteString(" LEFT JOIN `voucher_batch` ON `voucher_batch`.voucher_id = `voucher`.id") - } - // merchant_key_send depends on order.key - if need["merchant_key_send"] { - sb.WriteString(" LEFT JOIN `merchant_key_send` ON `order`." + escape("key") + " = `merchant_key_send`.key") - } + if req.MainTable == "order" { + if need["plan"] || need["key_batch"] { + sb.WriteString(" LEFT JOIN `plan` ON `plan`.id = `order`.plan_id") + } + if need["key_batch"] { + sb.WriteString(" LEFT JOIN `key_batch` ON `key_batch`.plan_id = `plan`.id") + } + if need["code_batch"] { + sb.WriteString(" LEFT JOIN `code_batch` ON `code_batch`.key_batch_id = `key_batch`.id") + } + if need["voucher"] { + sb.WriteString(" LEFT JOIN `voucher` ON `voucher`.channel_activity_id = `order_voucher`.channel_activity_id") + } + if need["voucher_batch"] { + sb.WriteString(" LEFT JOIN `voucher_batch` ON `voucher_batch`.voucher_id = `voucher`.id") + } + if need["merchant_key_send"] { + sb.WriteString(" LEFT JOIN `merchant_key_send` ON `order`." + escape("key") + " = `merchant_key_send`.key") + } + } args := []interface{}{} where := []string{} @@ -127,8 +132,8 @@ func BuildSQL(req BuildRequest, whitelist map[string]bool) (string, []interface{ if _, ok := req.Filters["merchant_out_biz_no_eq"]; ok { need["merchant_key_send"] = true } - if v, ok := req.Filters["creator_in"]; ok { - ids := []interface{}{} + if v, ok := req.Filters["creator_in"]; ok { + ids := []interface{}{} switch t := v.(type) { case []interface{}: ids = t @@ -146,20 +151,28 @@ func BuildSQL(req BuildRequest, whitelist map[string]bool) (string, []interface{ } ph := strings.Repeat("?,", len(ids)) ph = strings.TrimSuffix(ph, ",") - where = append(where, "`order`.creator IN ("+ph+")") - args = append(args, ids...) - } - if v, ok := req.Filters["create_time_between"]; ok { + if req.MainTable == "order_info" { + where = append(where, "`order_info`.user_id IN ("+ph+")") + } else { + where = append(where, "`order`.creator IN ("+ph+")") + } + args = append(args, ids...) + } + if v, ok := req.Filters["create_time_between"]; ok { var arr []interface{} b, _ := json.Marshal(v) json.Unmarshal(b, &arr) if len(arr) != 2 { return "", nil, errors.New("create_time_between requires 2 values") } - where = append(where, "`order`.create_time BETWEEN ? AND ?") - args = append(args, arr[0], arr[1]) - } - if v, ok := req.Filters["type_eq"]; ok { + if req.MainTable == "order_info" { + where = append(where, "`order_info`.create_time BETWEEN ? AND ?") + } else { + where = append(where, "`order`.create_time BETWEEN ? AND ?") + } + args = append(args, arr[0], arr[1]) + } + if v, ok := req.Filters["type_eq"]; ok { var tv int switch t := v.(type) { case float64: @@ -176,88 +189,132 @@ func BuildSQL(req BuildRequest, whitelist map[string]bool) (string, []interface{ tv = tv*10 + int(c-'0') } } - if tv == 1 || tv == 2 || tv == 3 { - where = append(where, "`order`.type = ?") - args = append(args, tv) - } - } - if v, ok := req.Filters["out_trade_no_eq"]; ok { - s := toString(v) - if s != "" { - where = append(where, "`order`.out_trade_no = ?") - args = append(args, s) - } - } - if v, ok := req.Filters["account_eq"]; ok { - s := toString(v) - if s != "" { - where = append(where, "`order`.account = ?") - args = append(args, s) - } - } - if v, ok := req.Filters["plan_id_eq"]; ok { - s := toString(v) - if s != "" { - where = append(where, "`order`.plan_id = ?") - args = append(args, s) - } - } - if v, ok := req.Filters["key_batch_id_eq"]; ok { - s := toString(v) - if s != "" { - where = append(where, "`order`.key_batch_id = ?") - args = append(args, s) - } - } - if v, ok := req.Filters["product_id_eq"]; ok { - s := toString(v) - if s != "" { - where = append(where, "`order`.product_id = ?") - args = append(args, s) - } - } - if v, ok := req.Filters["reseller_id_eq"]; ok { - s := toString(v) - if s != "" { - where = append(where, "`order`.reseller_id = ?") - args = append(args, s) - } - } - if v, ok := req.Filters["code_batch_id_eq"]; ok { - s := toString(v) - if s != "" { - where = append(where, "`order`.code_batch_id = ?") - args = append(args, s) - } - } - if v, ok := req.Filters["order_cash_cash_activity_id_eq"]; ok { - s := toString(v) - if s != "" { - where = append(where, "`order_cash`.cash_activity_id = ?") - args = append(args, s) - } - } - if v, ok := req.Filters["order_voucher_channel_activity_id_eq"]; ok { - s := toString(v) - if s != "" { - where = append(where, "`order_voucher`.channel_activity_id = ?") - args = append(args, s) - } - } - if v, ok := req.Filters["voucher_batch_channel_activity_id_eq"]; ok { - s := toString(v) - if s != "" { - where = append(where, "`voucher_batch`.channel_activity_id = ?") - args = append(args, s) - } - } - if v, ok := req.Filters["merchant_out_biz_no_eq"]; ok { - s := toString(v) - if s != "" { - where = append(where, "`merchant_key_send`.out_biz_no = ?") - args = append(args, s) - } - } + if tv == 1 || tv == 2 || tv == 3 { + if req.MainTable == "order_info" { + where = append(where, "`order_info`.type = ?") + } else { + where = append(where, "`order`.type = ?") + } + args = append(args, tv) + } + } + if v, ok := req.Filters["out_trade_no_eq"]; ok { + s := toString(v) + if s != "" { + if req.MainTable == "order_info" { + where = append(where, "`order_info`.out_order_no = ?") + } else { + where = append(where, "`order`.out_trade_no = ?") + } + args = append(args, s) + } + } + if v, ok := req.Filters["account_eq"]; ok { + s := toString(v) + if s != "" { + if req.MainTable == "order_info" { + where = append(where, "`order_info`.account = ?") + } else { + where = append(where, "`order`.account = ?") + } + args = append(args, s) + } + } + if v, ok := req.Filters["plan_id_eq"]; ok { + s := toString(v) + if s != "" { + if req.MainTable == "order_info" { + where = append(where, "`order_info`.activity_id = ?") + } else { + where = append(where, "`order`.plan_id = ?") + } + args = append(args, s) + } + } + if v, ok := req.Filters["key_batch_id_eq"]; ok { + s := toString(v) + if s != "" { + if req.MainTable == "order_info" { + where = append(where, "`order_info`.key_batch_name = ?") + } else { + where = append(where, "`order`.key_batch_id = ?") + } + args = append(args, s) + } + } + if v, ok := req.Filters["product_id_eq"]; ok { + s := toString(v) + if s != "" { + if req.MainTable == "order_info" { + where = append(where, "`order_info`.goods_id = ?") + } else { + where = append(where, "`order`.product_id = ?") + } + args = append(args, s) + } + } + if v, ok := req.Filters["reseller_id_eq"]; ok { + s := toString(v) + if s != "" { + if req.MainTable == "order_info" { + where = append(where, "`order_info`.merchant_id = ?") + } else { + where = append(where, "`order`.reseller_id = ?") + } + args = append(args, s) + } + } + if v, ok := req.Filters["code_batch_id_eq"]; ok { + s := toString(v) + if s != "" { + if req.MainTable == "order_info" { + where = append(where, "`order_info`.supplier_product_id = ?") + } else { + where = append(where, "`order`.code_batch_id = ?") + } + args = append(args, s) + } + } + if v, ok := req.Filters["order_cash_cash_activity_id_eq"]; ok { + s := toString(v) + if s != "" { + if req.MainTable == "order_info" { + where = append(where, "`order_cash`.activity_id = ?") + } else { + where = append(where, "`order_cash`.cash_activity_id = ?") + } + args = append(args, s) + } + } + if v, ok := req.Filters["order_voucher_channel_activity_id_eq"]; ok { + s := toString(v) + if s != "" { + if req.MainTable == "order_info" { + where = append(where, "`order_voucher`.channel_batch_no = ?") + } else { + where = append(where, "`order_voucher`.channel_activity_id = ?") + } + args = append(args, s) + } + } + if v, ok := req.Filters["voucher_batch_channel_activity_id_eq"]; ok { + s := toString(v) + if s != "" { + if req.MainTable == "order" { // only marketing schema has voucher_batch + where = append(where, "`voucher_batch`.channel_activity_id = ?") + args = append(args, s) + } + } + } + if v, ok := req.Filters["merchant_out_biz_no_eq"]; ok { + s := toString(v) + if s != "" { + if req.MainTable == "order" { // marketing only + where = append(where, "`merchant_key_send`.out_biz_no = ?") + } + args = append(args, s) + } + } if len(where) > 0 { sb.WriteString(" WHERE ") sb.WriteString(strings.Join(where, " AND ")) diff --git a/server/log/server-20251126.log b/server/log/server-20251126.log index 53af478..11e7375 100644 --- a/server/log/server-20251126.log +++ b/server/log/server-20251126.log @@ -374,3 +374,8 @@ job_id=47 sql=UPDATE export_jobs SET status=?, started_at=? WHERE id= ? args=[ru {"bytes":77,"duration_ms":16,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-26T17:54:11+08:00"} {"bytes":1614,"duration_ms":16,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-26T17:54:11+08:00"} {"bytes":1040,"duration_ms":51,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-26T17:54:16+08:00"} +{"bytes":1040,"duration_ms":55,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-26T18:12:45+08:00"} +{"bytes":914,"duration_ms":108,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-26T18:12:48+08:00"} +{"bytes":1614,"duration_ms":10,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-26T18:12:48+08:00"} +{"bytes":914,"duration_ms":107,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-26T18:12:51+08:00"} +{"bytes":1040,"duration_ms":51,"kind":"access","level":"INFO","method":"","path":"","query":"","remote":"","status":200,"trace_id":"","ts":"2025-11-26T18:15:41+08:00"}