package dao import ( "context" "crypto/md5" "database/sql" "encoding/json" "errors" "fmt" "net/url" "strings" "time" "go-common/app/service/openplatform/ticket-sales/model" "go-common/app/service/openplatform/ticket-sales/model/consts" "go-common/library/cache/redis" xsql "go-common/library/database/sql" "go-common/library/ecode" "github.com/gogo/protobuf/types" ) //订单相关常量 const ( cacheTimeout = 10 DefaultOrderPSize = 20 //默认每页数量 DefaultOrderOrderBy = "id desc" //默认排序 //sqlGetUserOrders 查询用户订单列表 sqlGetUserOrders = "SELECT %s FROM order_main WHERE uid=? AND is_deleted = 0 ORDER BY %s LIMIT %d,%d" //sqlGetUserItemOrders 查询用户已购买的某个项目订单 sqlGetUserItemOrders = "SELECT %s FROM order_main WHERE uid=? AND item_id=? AND status IN (%s)" //sqlCountUserOrders 查询用户订单数量 sqlCountUserOrders = "SELECT COUNT(*) FROM order_main WHERE uid=? AND is_deleted=0" //sqlGetOrders 查询订单列表 sqlGetOrders = "SELECT %s FROM order_main WHERE order_id IN (%s)" //sqlInsertOrderMains 批量写入order_main sqlInsertOrderMains = "INSERT INTO order_main(%s) VALUES %s" //sqlGetOrderDetails 查询订单详情 sqlGetOrderDetails = "SELECT %s FROM order_detail WHERE order_id IN (%s)" //sqlInsertOrderDetails 批量写入order_detail sqlInsertOrderDetails = "INSERT INTO order_detail(%s) VALUES %s" //sqlGetOrderSkus 查询order_sku sqlGetOrderSkus = "SELECT %s FROM order_sku WHERE order_id IN (%s)" //sqlInsertOrderSkus 批量写入order_sku sqlInsertOrderSkus = "INSERT INTO order_sku(%s) VALUES %s" //sqlGetBoughtSkus 获取已购买的sku sqlGetBoughtSkus = "SELECT `count` FROM order_sku WHERE order_id IN (%s) AND sku_id IN (%s)" //sqlGetOrderPayChs 获取支付流水 sqlGetOrderPayChs = "SELECT %s FROM order_pay_charge WHERE order_id IN (%s) AND paid=1" //获取结算对账订单(0元单) sqlGetSettleCompareOrders = "SELECT id,order_id FROM order_main WHERE ctime>=? and ctime? AND status IN (%s) AND pay_money=0 ORDER BY ctime,id LIMIT ?" //获取结算对帐退款单 sqlGetSettleCompareRefunds = "SELECT id,order_id,refund_apply_time FROM order_refund WHERE ctime>=? AND ctime? AND status IN (%s) AND refund_money=0 ORDER BY ctime,id LIMIT ?" ) //RawOrders 从db查询用户订单信息,包括以下情况 //* 按照订单号查询 //* 按照uid查分页 //* 按照uid+商品id+状态查询列表 func (d *Dao) RawOrders(ctx context.Context, req *model.OrderMainQuerier) (orders []*model.OrderMain, err error) { defer LogX(ctx, req, orders, err) o := new(model.OrderMain) sqls, args := pickOrderSQL(req, o.GetFields(nil)) q := sqls[0] if q == "" { return } r, err := d.db.Query(ctx, q, args...) if err != nil { if err == sql.ErrNoRows { err = nil } return } defer r.Close() for r.Next() { vptrs := make(map[int]interface{}) ptrs := o.GetPtrs(nil, vptrs) if err = r.Scan(ptrs...); err != nil { return } for k, v := range vptrs { json.Unmarshal([]byte(*ptrs[k].(*string)), v) } orders = append(orders, o) o = new(model.OrderMain) } return } //RawOrderCount 从db获取用户订单数目,当查询条件仅有uid时生效,否则返回0 func (d *Dao) RawOrderCount(ctx context.Context, req *model.OrderMainQuerier) (cnt int64, err error) { defer LogX(ctx, req, cnt, err) sqls, args := pickOrderSQL(req, nil) q := sqls[1] if q == "" { return } r := d.db.QueryRow(ctx, q, args...) err = r.Scan(&cnt) //缓存回源逻辑0会被当成没命中缓存 if cnt == 0 { cnt = -1 } return } //RawOrderDetails 从db获取订单详细 func (d *Dao) RawOrderDetails(ctx context.Context, oids []int64) (orders map[int64]*model.OrderDetail, err error) { defer LogX(ctx, oids, orders, err) lo := len(oids) if lo == 0 { return } a := make([]interface{}, lo) for k, v := range oids { a[k] = v } o := new(model.OrderDetail) f := o.GetFields(nil) q := fmt.Sprintf(sqlGetOrderDetails, "`"+strings.Join(f, "`,`")+"`", strings.Repeat(",?", lo)[1:]) r, err := d.db.Query(ctx, q, a...) if err != nil { if err == sql.ErrNoRows { err = nil } return } defer r.Close() orders = make(map[int64]*model.OrderDetail, lo) for r.Next() { vptrs := make(map[int]interface{}) ptrs := o.GetPtrs(nil, vptrs) if err = r.Scan(ptrs...); err != nil { return } for k, v := range vptrs { json.Unmarshal([]byte(*ptrs[k].(*string)), v) } o.Decrypt(d.c.Encrypt) orders[o.OrderID] = o o = new(model.OrderDetail) } return } //RawOrderSKUs 从db获取订单的sku func (d *Dao) RawOrderSKUs(ctx context.Context, oids []int64) (skus map[int64][]*model.OrderSKU, err error) { defer LogX(ctx, oids, skus, err) lo := len(oids) if lo == 0 { return } a := make([]interface{}, lo) for k, v := range oids { a[k] = v } o := new(model.OrderSKU) f := o.GetFields(nil) q := fmt.Sprintf(sqlGetOrderSkus, "`"+strings.Join(f, "`,`")+"`", strings.Repeat(",?", lo)[1:]) r, err := d.db.Query(ctx, q, a...) if err != nil { if err == sql.ErrNoRows { err = nil } return } defer r.Close() skus = make(map[int64][]*model.OrderSKU, lo) for r.Next() { vptrs := make(map[int]interface{}) ptrs := o.GetPtrs(nil, vptrs) if err = r.Scan(ptrs...); err != nil { return } for k, v := range vptrs { json.Unmarshal([]byte(*ptrs[k].(*string)), v) } skus[o.OrderID] = append(skus[o.OrderID], o) o = new(model.OrderSKU) } return } //RawBoughtCount 按照票种获取用户已购的订单票数 func (d *Dao) RawBoughtCount(ctx context.Context, uid string, itemID int64, skuIDs []int64) (cnt int64, err error) { query := &model.OrderMainQuerier{ UID: uid, ItemID: itemID, Status: []int16{consts.OrderStatusUnpaid, consts.OrderStatusPaid}, } orders, err := d.RawOrders(ctx, query) if err != nil { return } //存在部分退款,要减去已退款票数 pt := false lo := len(orders) oids := make([]int64, lo) for k, v := range orders { if v.RefundStatus == consts.RefundStatusPtRefunded { pt = true } cnt += v.Count oids[k] = v.OrderID } ls := len(skuIDs) //查具体sku的,要再次从order_sku表统计 if ls > 0 && lo > 0 { cnt, err = d.rawBoughtSkusCnt(ctx, oids, skuIDs) if err != nil { return } } //部分退款的减去已退款张数 if pt { var rCnt int64 rCnt, err = d.rawRefundTicketCnt(ctx, oids) if err != nil { return } cnt -= rCnt } return } //rawBoughtSkusCnt 按照skuID统计用户购买数 func (d *Dao) rawBoughtSkusCnt(ctx context.Context, oids []int64, skuIDs []int64) (cnt int64, err error) { lo := len(oids) ls := len(skuIDs) if lo == 0 || ls == 0 { err = ecode.RequestErr return } q := fmt.Sprintf(sqlGetBoughtSkus, strings.Repeat(",?", lo)[1:], strings.Repeat(",?", ls)[1:]) a := make([]interface{}, lo+ls) for k, v := range oids { a[k] = v } for k, v := range skuIDs { a[k+lo] = v } r, err := d.db.Query(ctx, q, a...) if err != nil { return } defer r.Close() var c int64 for r.Next() { if err = r.Scan(&c); err != nil { return } cnt += c } return } //RawOrderPayCharges 从db获取订单流水 func (d *Dao) RawOrderPayCharges(ctx context.Context, oids []int64) (chs map[int64]*model.OrderPayCharge, err error) { defer LogX(ctx, oids, chs, err) lo := len(oids) if lo == 0 { return } a := make([]interface{}, lo) for k, v := range oids { a[k] = v } o := new(model.OrderPayCharge) f := o.GetFields(nil) q := fmt.Sprintf(sqlGetOrderPayChs, "`"+strings.Join(f, "`,`")+"`", strings.Repeat(",?", lo)[1:]) r, err := d.db.Query(ctx, q, a...) if err != nil { if err == sql.ErrNoRows { err = nil } return } defer r.Close() chs = make(map[int64]*model.OrderPayCharge, lo) for r.Next() { ptrs := o.GetPtrs(&types.FieldMask{Paths: f}, nil) if err = r.Scan(ptrs...); err != nil { return } chs[o.OrderID] = o o = new(model.OrderPayCharge) } return } //CacheOrders 从缓存获取订单基础信息 func (d *Dao) CacheOrders(ctx context.Context, req *model.OrderMainQuerier) (orders []*model.OrderMain, err error) { pool := d.redis.Get(ctx) defer func() { pool.Close() LogX(ctx, req, orders, err) }() var keys []interface{} if l := len(req.OrderID); l > 0 { keys = make([]interface{}, l) for k, v := range req.OrderID { keys[k] = fmt.Sprintf("%s:%d", model.CacheKeyOrderMn, v) } } else if key := oidCacheKey(req); key != "" { //如果查的是列表,先查出列表缓存的orderId,再根据orderId查订单信息 var b []byte key = model.CacheKeyOrderList + ":" + key if b, err = redis.Bytes(pool.Do("GET", key)); err != nil { if err == redis.ErrNil { err = nil } return } s := string(b) LogX(ctx, []string{"GET", key}, s, err) oids := strings.Split(s, ",") keys = make([]interface{}, len(oids)) for k, v := range oids { keys[k] = model.CacheKeyOrderMn + ":" + v } } if len(keys) == 0 { return } var data [][]byte if data, err = redis.ByteSlices(pool.Do("MGET", keys...)); err != nil { return } LogX(ctx, append([]interface{}{"MGET"}, keys...), data, err) for _, v := range data { if v != nil { o := &model.OrderMain{} orders = append(orders, o) json.Unmarshal(v, o) } } return } //CacheOrderCount 从缓存获取订单数目 func (d *Dao) CacheOrderCount(ctx context.Context, req *model.OrderMainQuerier) (cnt int64, err error) { pool := d.redis.Get(ctx) defer func() { pool.Close() LogX(ctx, req, cnt, err) }() if key := oidCacheKey(req); key != "" { if cnt, err = redis.Int64(pool.Do("GET", model.CacheKeyOrderCnt+":"+key)); err == redis.ErrNil { err = nil } } return } //CacheOrderDetails 从缓存获取订单详细 func (d *Dao) CacheOrderDetails(ctx context.Context, oids []int64) (orders map[int64]*model.OrderDetail, err error) { pool := d.redis.Get(ctx) defer func() { pool.Close() LogX(ctx, oids, orders, err) }() lo := len(oids) keys := make([]interface{}, lo) for k, v := range oids { keys[k] = fmt.Sprintf("%s:%d", model.CacheKeyOrderDt, v) } var data [][]byte if data, err = redis.ByteSlices(pool.Do("MGET", keys...)); err != nil { return } LogX(ctx, append([]interface{}{"MGET"}, keys...), data, nil) orders = make(map[int64]*model.OrderDetail, lo) for k, v := range oids { if data[k] == nil { continue } o := &model.OrderDetail{} if err = json.Unmarshal(data[k], o); err != nil { err = nil } else { orders[v] = o } } return } //CacheOrderSKUs 获取订单sku缓存 func (d *Dao) CacheOrderSKUs(ctx context.Context, oids []int64) (skus map[int64][]*model.OrderSKU, err error) { pool := d.redis.Get(ctx) defer func() { pool.Close() LogX(ctx, oids, skus, err) }() lo := len(oids) keys := make([]interface{}, lo) for k, v := range oids { keys[k] = fmt.Sprintf("%s:%d", model.CacheKeyOrderSKU, v) } var data [][]byte if data, err = redis.ByteSlices(pool.Do("MGET", keys...)); err != nil { return } LogX(ctx, append([]interface{}{"MGET"}, keys...), data, nil) skus = make(map[int64][]*model.OrderSKU, lo) for k, v := range oids { if data[k] == nil { continue } o := []*model.OrderSKU{} if err = json.Unmarshal(data[k], &o); err != nil { err = nil } else { skus[v] = o } } return } //CacheOrderPayCharges 从缓存获取订单流水 func (d *Dao) CacheOrderPayCharges(ctx context.Context, oids []int64) (chs map[int64]*model.OrderPayCharge, err error) { pool := d.redis.Get(ctx) defer func() { pool.Close() LogX(ctx, oids, chs, err) }() lo := len(oids) if lo == 0 { return } keys := make([]interface{}, lo) for k, v := range oids { keys[k] = fmt.Sprintf("%s:%d", model.CacheKeyOrderPayCh, v) } var data [][]byte if data, err = redis.ByteSlices(pool.Do("MGET", keys...)); err != nil { return } LogX(ctx, append([]interface{}{"MGET"}, keys...), data, nil) chs = make(map[int64]*model.OrderPayCharge, lo) for k, v := range oids { if data[k] == nil { continue } ch := &model.OrderPayCharge{} if err = json.Unmarshal(data[k], ch); err != nil { err = nil } else { chs[v] = ch } } return } //AddCacheOrders 设置订单基础信息缓存 func (d *Dao) AddCacheOrders(ctx context.Context, req *model.OrderMainQuerier, res []*model.OrderMain) (err error) { pool := d.redis.Get(ctx) defer func() { pool.Flush() pool.Close() LogX(ctx, []interface{}{req, res}, nil, err) }() data := make([]interface{}, len(res)*2) var sOids string for k, v := range res { if sOids == "" { sOids = fmt.Sprintf("%d", v.OrderID) } else { sOids += fmt.Sprintf(",%d", v.OrderID) } b, _ := json.Marshal(v) data[k*2] = fmt.Sprintf("%s:%d", model.CacheKeyOrderMn, v.OrderID) data[k*2+1] = b } //设置列表orderID缓存 if key := oidCacheKey(req); key != "" { arg := []interface{}{model.CacheKeyOrderList + ":" + key, cacheTimeout, sOids} LogX(ctx, append([]interface{}{"SETEX"}, arg...), nil, nil) if err = pool.Send("SETEX", arg...); err != nil { return } } LogX(ctx, append([]interface{}{"MSET"}, data...), nil, nil) if err = pool.Send("MSET", data...); err != nil { return } for i := 0; i < len(data); i += 2 { pool.Send("EXPIRE", data[i], cacheTimeout) } return } //AddCacheOrderCount 设置订单数目缓存 func (d *Dao) AddCacheOrderCount(ctx context.Context, req *model.OrderMainQuerier, res int64) (err error) { pool := d.redis.Get(ctx) defer func() { pool.Close() LogX(ctx, []interface{}{req, res}, nil, err) }() if key := oidCacheKey(req); key != "" { _, err = pool.Do("SETEX", model.CacheKeyOrderCnt+":"+key, cacheTimeout, res) } return } //AddCacheOrderDetails 增加订单详细缓存 func (d *Dao) AddCacheOrderDetails(ctx context.Context, orders map[int64]*model.OrderDetail) (err error) { pool := d.redis.Get(ctx) defer func() { pool.Flush() pool.Close() LogX(ctx, orders, nil, err) }() data := make([]interface{}, len(orders)*2) i := 0 for k, v := range orders { key := fmt.Sprintf("%s:%d", model.CacheKeyOrderDt, k) var b []byte b, _ = json.Marshal(v) data[i] = key data[i+1] = b i += 2 } LogX(ctx, append([]interface{}{"MSET"}, data...), nil, nil) if err = pool.Send("MSET", data...); err != nil { return } for i := 0; i < len(data); i += 2 { pool.Send("EXPIRE", data[i], cacheTimeout) } return } //AddCacheOrderSKUs 增加订单sku缓存 func (d *Dao) AddCacheOrderSKUs(ctx context.Context, skus map[int64][]*model.OrderSKU) (err error) { pool := d.redis.Get(ctx) defer func() { pool.Flush() pool.Close() LogX(ctx, skus, nil, err) }() data := make([]interface{}, len(skus)*2) i := 0 for k, v := range skus { key := fmt.Sprintf("%s:%d", model.CacheKeyOrderSKU, k) var b []byte b, err = json.Marshal(v) data[i] = key data[i+1] = b i += 2 } LogX(ctx, append([]interface{}{"MSET"}, data...), nil, nil) if err = pool.Send("MSET", data...); err != nil { return } for i := 0; i < len(data); i += 2 { pool.Send("EXPIRE", data[i], cacheTimeout) } return } //AddCacheOrderPayCharges 增加订单流水缓存 func (d *Dao) AddCacheOrderPayCharges(ctx context.Context, chs map[int64]*model.OrderPayCharge) (err error) { pool := d.redis.Get(ctx) defer func() { pool.Flush() pool.Close() LogX(ctx, chs, nil, err) }() data := make([]interface{}, len(chs)*2) i := 0 for k, v := range chs { key := fmt.Sprintf("%s:%d", model.CacheKeyOrderPayCh, k) var b []byte b, _ = json.Marshal(v) data[i] = key data[i+1] = b i += 2 } LogX(ctx, append([]interface{}{"MSET"}, data...), nil, nil) if err = pool.Send("MSET", data...); err != nil { return } for i := 0; i < len(data); i += 2 { pool.Send("EXPIRE", data[i], cacheTimeout) } return } //DelCacheOrders 删除订单相关缓存,如果是新增或删除订单,要删除这个uid的订单列表缓存 func (d *Dao) DelCacheOrders(ctx context.Context, req *model.OrderMainQuerier) { pool := d.redis.Get(ctx) var ret interface{} defer func() { pool.Close() LogX(ctx, req, ret, nil) }() for _, v := range req.OrderID { ret, _ = pool.Do("DEL", fmt.Sprintf("%s:%d", model.CacheKeyOrderMn, v), fmt.Sprintf("%s:%d", model.CacheKeyOrderDt, v), fmt.Sprintf("%s:%d", model.CacheKeyOrderSKU, v), ) } if key := oidCacheKey(req); key != "" { ret, _ = pool.Do("DEL", model.CacheKeyOrderList+":"+key, model.CacheKeyOrderCnt+":"+key) } } //TxInsertOrders 插入订单表,返回成功行数 func (d *Dao) TxInsertOrders(tx *xsql.Tx, orders []*model.OrderMain) (cnt int64, err error) { lo := len(orders) if lo == 0 { return } f := orders[0].GetFields(&types.FieldMask{Paths: []string{"ctime", "mtime"}}) lf := len(f) hlds := model.InsPlHlds(lf, lo) a := make([]interface{}, lf*lo) i := 0 for _, o := range orders { vals := o.GetVals(&types.FieldMask{Paths: f}, true) copy(a[i:], vals) i += lf } r, err := tx.Exec(fmt.Sprintf(sqlInsertOrderMains, "`"+strings.Join(f, "`,`")+"`", hlds), a...) if err != nil { return } cnt, err = r.RowsAffected() return } //TxInsertOrderDetails 写入orderDetail表 func (d *Dao) TxInsertOrderDetails(tx *xsql.Tx, orders []*model.OrderDetail) (cnt int64, err error) { for _, v := range orders { v.Encrypt(d.c.Encrypt) } lo := len(orders) if lo == 0 { return } f := orders[0].GetFields(&types.FieldMask{Paths: []string{"ctime", "mtime"}}) lf := len(f) hlds := model.InsPlHlds(lf, lo) a := make([]interface{}, lf*lo) i := 0 for _, o := range orders { vals := o.GetVals(&types.FieldMask{Paths: f}, true) copy(a[i:], vals) i += lf } r, err := tx.Exec(fmt.Sprintf(sqlInsertOrderDetails, "`"+strings.Join(f, "`,`")+"`", hlds), a...) if err != nil { cnt = 0 return } cnt, err = r.RowsAffected() return } //TxInsertOrderSKUs 增加订单Sku func (d *Dao) TxInsertOrderSKUs(tx *xsql.Tx, orders []*model.OrderSKU) (cnt int64, err error) { lo := len(orders) if lo == 0 { return } f := orders[0].GetFields(&types.FieldMask{Paths: []string{"ctime", "mtime"}}) lf := len(f) hlds := model.InsPlHlds(lf, lo) a := make([]interface{}, lf*lo) i := 0 for _, o := range orders { vals := o.GetVals(&types.FieldMask{Paths: f}, true) copy(a[i:], vals) i += lf } r, err := tx.Exec(fmt.Sprintf(sqlInsertOrderSkus, "`"+strings.Join(f, "`,`")+"`", hlds), a...) if err != nil { cnt = 0 return } cnt, err = r.RowsAffected() return } //OrderID 获取订单号的方法 func (d *Dao) OrderID(ctx context.Context, n int) ([]int64, error) { if n <= 0 { return nil, nil } if _, ok := d.c.URLs["basecenter"]; !ok { return nil, errors.New("miss basecenter's url conf") } u := d.c.URLs["basecenter"] var res struct { Errno int32 `json:"errno"` Data []int64 `json:"data"` } uv := url.Values{} uv.Set("app_id", d.c.BaseCenter.AppID) uv.Set("app_token", d.c.BaseCenter.Token) uv.Set("count", fmt.Sprintf("%d", n)) if err := d.httpClientR.Get(ctx, u+"/orderid/get", "", uv, &res); err != nil { return nil, err } if len(res.Data) == 0 { return nil, ecode.TicketGetOidFail } return res.Data, nil } //pickOrderSQL 查订单的sql,返回sqls:{0:查列表的sql, 1:查数量的sql}, args:需要代入的变量 func pickOrderSQL(q *model.OrderMainQuerier, fields []string) (sqls []string, args []interface{}) { sqls = make([]string, 2) var f string if len(fields) > 0 { f = "`" + strings.Join(fields, "`,`") + "`" } if l := len(q.OrderID); l > 0 { if f != "" { sqls[0] = fmt.Sprintf(sqlGetOrders, f, strings.Repeat(",?", l)[1:]) } args = make([]interface{}, len(q.OrderID)) for k, v := range q.OrderID { args[k] = v } return } if l := len(q.Status); l > 0 && q.ItemID > 0 { if f != "" { sqls[0] = fmt.Sprintf(sqlGetUserItemOrders, f, strings.Repeat(",?", l)[1:]) } args = make([]interface{}, 2+l) args[0] = q.UID args[1] = q.ItemID for k, v := range q.Status { args[k+2] = v } return } if q.OrderBy == "" { q.OrderBy = DefaultOrderOrderBy } if q.Limit == 0 { q.Limit = DefaultOrderPSize } if f != "" { sqls[0] = fmt.Sprintf(sqlGetUserOrders, f, q.OrderBy, q.Offset, q.Limit) } sqls[1] = sqlCountUserOrders args = []interface{}{q.UID} return } //oidCacheKey orderId列表的缓存key, 返回空不缓存列表 func oidCacheKey(q *model.OrderMainQuerier) string { s := "" if len(q.OrderID) > 0 { return s } if q.OrderBy == "" { q.OrderBy = DefaultOrderOrderBy } if q.Limit == 0 { q.Limit = DefaultOrderPSize } //仅缓存第一页 if q.Offset > 0 || q.Limit != DefaultOrderPSize || strings.ToLower(q.OrderBy) != DefaultOrderOrderBy { return "" } if q.UID != "" { s = "&uid=" + q.UID } if q.ItemID > 0 { s += fmt.Sprintf("&item_id=%d", q.ItemID) } fs := map[string][]int16{ "status": q.Status, "sub_status": q.SubStatus, "refund_status": q.RefundStatus, } for k, v := range fs { if len(v) > 0 { s += fmt.Sprintf("&%s=%s", k, strings.Trim(strings.Join(strings.Fields(fmt.Sprint(v)), ","), "[]")) } } ls := len(s) if ls > 32 { return fmt.Sprintf("%x", md5.Sum([]byte(s[1:]))) } if ls > 2 { return s[1:] } //空缓存key return "nil" } //RawGetSettleOrders 获取待结算订单 func (d *Dao) RawGetSettleOrders(ctx context.Context, bt time.Time, et time.Time, id int64, size int) (res *model.SettleOrders, offset int64, err error) { q := fmt.Sprintf(sqlGetSettleCompareOrders, "?,?") if size > 200 || size <= 0 { size = 200 } r, err := d.db.Query(ctx, q, bt.Format("2006-01-02"), et.Format("2006-01-02"), id, consts.OrderStatusPaid, consts.OrderStatusRefunded, size+1) if err != nil { if err == sql.ErrNoRows { err = nil } return } defer r.Close() res = &model.SettleOrders{} res.Data = make([]*model.SettleOrder, 0, size+1) for r.Next() { o := &model.SettleOrder{} if err = r.Scan(&o.ID, &o.OrderID); err != nil { return } res.Data = append(res.Data, o) } l := len(res.Data) if l > size { res.Data = res.Data[:l-1] offset = res.Data[l-2].ID } return } //RawGetSettleRefunds 获取待结算退款订单 func (d *Dao) RawGetSettleRefunds(ctx context.Context, bt time.Time, et time.Time, id int64, size int) (res *model.SettleOrders, offset int64, err error) { q := fmt.Sprintf(sqlGetSettleCompareRefunds, "?") if size > 200 || size <= 0 { size = 200 } r, err := d.db.Query(ctx, q, bt.Format("2006-01-02"), et.Format("2006-01-02"), id, consts.RefundTxStatusSucc, size+1) if err != nil { if err == sql.ErrNoRows { err = nil } return } defer r.Close() res = &model.SettleOrders{} res.Data = make([]*model.SettleOrder, 0) for r.Next() { o := &model.SettleOrder{} if err = r.Scan(&o.RefID, &o.OrderID, &o.RefundApplyTime); err != nil { return } res.Data = append(res.Data, o) } l := len(res.Data) if l > size { res.Data = res.Data[:l-1] offset = res.Data[l-2].RefID } return }