package model import ( "app-cloudep-trade-service/internal/domain" "context" "errors" "time" "github.com/zeromicro/go-zero/core/stores/mon" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) var _ OrderModel = (*customOrderModel)(nil) type ( // OrderModel is an interface to be customized, add more methods here, // and implement the added methods in customOrderModel. OrderModel interface { orderModel UpdateStatus(ctx context.Context, data UpdateStatusReq) (*mongo.UpdateResult, error) UpdateTimeoutOrder(ctx context.Context, req UpdateTimeoutReq) (*mongo.UpdateResult, error) DeleteByBusinessID(ctx context.Context, id string) (*mongo.UpdateResult, error) FindOneBusinessID(ctx context.Context, id string) (*Order, error) ListOrder(ctx context.Context, req GetOrderListReq) ([]Order, int64, error) } customOrderModel struct { *defaultOrderModel } UpdateStatusReq struct { BusinessID string Status int64 } UpdateTimeoutReq struct { CreateTimeBefore int64 } GetOrderListReq struct { PageIndex int64 `json:"page_index" validate:"required"` PageSize int64 `json:"page_size" validate:"required"` ReferenceID string `json:"reference_id"` ReferenceUID string `json:"reference_uid"` BusinessID string `json:"business_id"` UID string `json:"uid"` OrderType int `json:"order_type"` DirectionType []int64 `json:"direction_type"` OrderStatus []int64 `json:"order_status"` StartCreateTime int64 `json:"start_create_time"` EndCreateTime int64 `json:"end_create_time"` StartUpdateTime int64 `json:"start_update_time"` EndUpdateTime int64 `json:"end_update_time"` StartOrderArrivalTime int64 `json:"start_order_arrival_time"` EndOrderArrivalTime int64 `json:"end_order_arrival_time"` StartOrderPaymentTime int64 `json:"start_order_payment_time"` EndOrderPaymentTime int64 `json:"end_order_payment_time"` CryptoType string `json:"crypto_type"` TxHash string `json:"tx_hash"` } ) // NewOrderModel returns a model for the mongo. func NewOrderModel(url, db, collection string, opts ...mon.Option) OrderModel { conn := mon.MustNewModel(url, db, collection, opts...) return &customOrderModel{ defaultOrderModel: newDefaultOrderModel(conn), } } func (m *customOrderModel) UpdateStatus(ctx context.Context, data UpdateStatusReq) (*mongo.UpdateResult, error) { // 初始化 updates map updates := make(map[string]any) // 更新 update_time 和 status updates["update_time"] = time.Now().UTC().UnixNano() updates["order_status"] = data.Status // 使用 updates map 作為 $set 的內容 res, err := m.conn.UpdateOne(ctx, bson.M{ "business_id": data.BusinessID, "$or": []bson.M{ {"delete_time": bson.M{"$exists": false}}, {"delete_time": 0}, }, }, bson.M{"$set": updates}, // 使用 updates 而不是整個 data ) return res, err } func (m *customOrderModel) UpdateTimeoutOrder(ctx context.Context, req UpdateTimeoutReq) (*mongo.UpdateResult, error) { // 構建過濾條件,選擇創建時間在指定時間之前且狀態為 0 (創建) 的項目 filter := bson.M{ "create_time": bson.M{"$lt": req.CreateTimeBefore}, "status": domain.OrderStatusCreated, "$or": []bson.M{ {"delete_time": bson.M{"$exists": false}}, {"delete_time": 0}, }, } // 更新內容,將狀態設置為 11,並更新 update_time updates := bson.M{ "$set": bson.M{ "status": domain.OrderStatusTimeout, "update_time": time.Now().UTC().UnixNano(), }, } // 執行更新操作 res, err := m.conn.UpdateOne(ctx, filter, updates) return res, err } func (m *customOrderModel) DeleteByBusinessID(ctx context.Context, id string) (*mongo.UpdateResult, error) { filter := bson.M{ "business_id": id, "$or": []bson.M{ {"delete_time": bson.M{"$exists": false}}, {"delete_time": 0}, }, } updates := bson.M{ "$set": bson.M{ "delete_time": time.Now().UTC().UnixNano(), "update_time": time.Now().UTC().UnixNano(), }, } // 執行更新操作 res, err := m.conn.UpdateOne(ctx, filter, updates) return res, err } func (m *defaultOrderModel) FindOneBusinessID(ctx context.Context, id string) (*Order, error) { var data Order filter := bson.M{"delete_time": bson.M{"$in": []any{0, nil}}} filter["business_id"] = id err := m.conn.FindOne(ctx, &data, filter) switch { case err == nil: return &data, nil case errors.Is(err, mon.ErrNotFound): return nil, ErrNotFound default: return nil, err } } func (m *customOrderModel) ListOrder(ctx context.Context, req GetOrderListReq) ([]Order, int64, error) { // 定義查詢過濾器 filter := bson.M{ "delete_time": bson.M{"$in": []any{0, nil}}, } // 添加查詢條件 if req.ReferenceID != "" { filter["reference_id"] = req.ReferenceID } if req.ReferenceUID != "" { filter["reference_uid"] = req.ReferenceUID } if req.BusinessID != "" { filter["business_id"] = req.BusinessID } if req.UID != "" { filter["order_uid"] = req.UID } if req.OrderType != 0 { filter["order_type"] = req.OrderType } if len(req.DirectionType) > 0 { filter["direction_type"] = bson.M{"$in": req.DirectionType} } if len(req.OrderStatus) > 0 { filter["order_status"] = bson.M{"$in": req.OrderStatus} } // 處理時間範圍 if req.StartCreateTime != 0 { filter["create_time"] = bson.M{"$gte": req.StartCreateTime} } if req.EndCreateTime != 0 { filter["create_time"] = bson.M{"$lte": req.EndCreateTime} } if req.StartUpdateTime != 0 { filter["update_time"] = bson.M{"$gte": req.StartUpdateTime} } if req.EndUpdateTime != 0 { filter["update_time"] = bson.M{"$lte": req.EndUpdateTime} } if req.StartOrderArrivalTime != 0 { filter["order_arrival_time"] = bson.M{"$gte": req.StartOrderArrivalTime} } if req.EndOrderArrivalTime != 0 { filter["order_arrival_time"] = bson.M{"$lte": req.EndOrderArrivalTime} } if req.StartOrderPaymentTime != 0 { filter["order_payment_time"] = bson.M{"$gte": req.StartOrderPaymentTime} } if req.EndOrderPaymentTime != 0 { filter["order_payment_time"] = bson.M{"$lte": req.EndOrderPaymentTime} } if req.CryptoType != "" { filter["crypto_type"] = req.CryptoType } if req.TxHash != "" { filter["tx_hash"] = req.TxHash } // 計算符合條件的總數量 totalCount, err := m.conn.CountDocuments(ctx, filter) if err != nil { return nil, 0, err } // 設定查詢選項,包含分頁 findOptions := options.Find() findOptions.SetSkip((req.PageIndex - 1) * req.PageSize) findOptions.SetLimit(req.PageSize) // 執行查詢 var orders []Order err = m.conn.Find(ctx, &orders, filter, findOptions) if err != nil { return nil, 0, err } return orders, totalCount, nil }