初始化项目

This commit is contained in:
2025-12-10 09:02:41 +08:00
parent 3a40846865
commit 3c55577df8
19 changed files with 2653 additions and 10 deletions

276
dao/order_dao.go Normal file
View File

@@ -0,0 +1,276 @@
package dao
import (
"context"
"errors"
"fmt"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"order/model/entity"
)
// OrderDao 订单数据访问对象
// 支持按状态拆分的订单表操作
type OrderDao struct {
collections map[entity.OrderStatus]*mongo.Collection
}
// NewOrderDao 创建订单DAO实例
func NewOrderDao(collections map[entity.OrderStatus]*mongo.Collection) *OrderDao {
return &OrderDao{
collections: collections,
}
}
// getCollection 根据订单状态获取对应的集合
func (d *OrderDao) getCollection(status entity.OrderStatus) (*mongo.Collection, error) {
collection, exists := d.collections[status]
if !exists {
return nil, fmt.Errorf("collection for status %s not found", status)
}
return collection, nil
}
// CreatePendingOrder 创建待支付订单
func (d *OrderDao) CreatePendingOrder(ctx context.Context, order *entity.OrderPending) error {
collection, err := d.getCollection(entity.OrderStatusPending)
if err != nil {
return err
}
order.ID = primitive.NewObjectID()
order.CreatedAt = time.Now()
order.UpdatedAt = time.Now()
_, err = collection.InsertOne(ctx, order)
return err
}
// GetOrderByNo 根据订单号查询订单(自动识别状态)
func (d *OrderDao) GetOrderByNo(ctx context.Context, tenantID, orderNo string) (interface{}, entity.OrderStatus, error) {
// 按状态优先级搜索(从最新状态开始)
statuses := []entity.OrderStatus{
entity.OrderStatusCompleted,
entity.OrderStatusShipped,
entity.OrderStatusPaid,
entity.OrderStatusPending,
}
for _, status := range statuses {
collection, err := d.getCollection(status)
if err != nil {
continue
}
switch status {
case entity.OrderStatusPending:
var order entity.OrderPending
if err := d.findOrderByNo(collection, ctx, tenantID, orderNo, &order); err == nil {
return &order, status, nil
}
case entity.OrderStatusPaid:
var order entity.OrderPaid
if err := d.findOrderByNo(collection, ctx, tenantID, orderNo, &order); err == nil {
return &order, status, nil
}
case entity.OrderStatusShipped:
var order entity.OrderShipped
if err := d.findOrderByNo(collection, ctx, tenantID, orderNo, &order); err == nil {
return &order, status, nil
}
case entity.OrderStatusCompleted:
var order entity.OrderCompleted
if err := d.findOrderByNo(collection, ctx, tenantID, orderNo, &order); err == nil {
return &order, status, nil
}
}
}
return nil, "", errors.New("order not found")
}
// findOrderByNo 通用订单查询方法
func (d *OrderDao) findOrderByNo(collection *mongo.Collection, ctx context.Context, tenantID, orderNo string, result interface{}) error {
filter := bson.M{
"tenant_id": tenantID,
"order_no": orderNo,
}
err := collection.FindOne(ctx, filter).Decode(result)
if err == mongo.ErrNoDocuments {
return errors.New("order not found")
}
return err
}
// MoveOrderToStatus 将订单从一个状态移动到另一个状态
func (d *OrderDao) MoveOrderToStatus(ctx context.Context, fromStatus, toStatus entity.OrderStatus, tenantID, orderNo string, updateData bson.M) error {
// 获取源集合
srcCollection, err := d.getCollection(fromStatus)
if err != nil {
return err
}
// 获取目标集合
destCollection, err := d.getCollection(toStatus)
if err != nil {
return err
}
// 查找源订单
var orderData bson.M
filter := bson.M{
"tenant_id": tenantID,
"order_no": orderNo,
}
err = srcCollection.FindOne(ctx, filter).Decode(&orderData)
if err != nil {
return err
}
// 更新数据
orderData["updated_at"] = time.Now()
for key, value := range updateData {
orderData[key] = value
}
// 插入到目标集合
_, err = destCollection.InsertOne(ctx, orderData)
if err != nil {
return err
}
// 从源集合删除
_, err = srcCollection.DeleteOne(ctx, filter)
return err
}
// UpdatePendingOrder 更新待支付订单
func (d *OrderDao) UpdatePendingOrder(ctx context.Context, tenantID, orderNo string, update bson.M) error {
collection, err := d.getCollection(entity.OrderStatusPending)
if err != nil {
return err
}
update["updated_at"] = time.Now()
_, err = collection.UpdateOne(ctx, bson.M{
"tenant_id": tenantID,
"order_no": orderNo,
}, bson.M{"$set": update})
return err
}
// ListOrdersByStatus 根据状态查询订单列表
func (d *OrderDao) ListOrdersByStatus(ctx context.Context, status entity.OrderStatus, tenantID, userID string, page, pageSize int) (interface{}, int64, error) {
collection, err := d.getCollection(status)
if err != nil {
return nil, 0, err
}
// 构建查询条件
filter := bson.M{"tenant_id": tenantID}
if userID != "" {
filter["user_id"] = userID
}
// 计算总数
total, err := collection.CountDocuments(ctx, filter)
if err != nil {
return nil, 0, err
}
// 分页查询
skip := int64((page - 1) * pageSize)
opt := options.Find().
SetSort(bson.D{{Key: "created_at", Value: -1}}).
SetSkip(skip).
SetLimit(int64(pageSize))
cursor, err := collection.Find(ctx, filter, opt)
if err != nil {
return nil, 0, err
}
defer cursor.Close(ctx)
// 根据状态返回对应的订单类型
switch status {
case entity.OrderStatusPending:
var orders []entity.OrderPending
if err := cursor.All(ctx, &orders); err != nil {
return nil, 0, err
}
return orders, total, nil
case entity.OrderStatusPaid:
var orders []entity.OrderPaid
if err := cursor.All(ctx, &orders); err != nil {
return nil, 0, err
}
return orders, total, nil
case entity.OrderStatusShipped:
var orders []entity.OrderShipped
if err := cursor.All(ctx, &orders); err != nil {
return nil, 0, err
}
return orders, total, nil
case entity.OrderStatusCompleted:
var orders []entity.OrderCompleted
if err := cursor.All(ctx, &orders); err != nil {
return nil, 0, err
}
return orders, total, nil
default:
return nil, 0, errors.New("unsupported order status")
}
}
// GetExpiredPendingOrders 获取过期的待支付订单
func (d *OrderDao) GetExpiredPendingOrders(ctx context.Context, tenantID string) ([]entity.OrderPending, error) {
collection, err := d.getCollection(entity.OrderStatusPending)
if err != nil {
return nil, err
}
filter := bson.M{
"tenant_id": tenantID,
"expired_at": bson.M{"$lte": time.Now()},
}
cursor, err := collection.Find(ctx, filter)
if err != nil {
return nil, err
}
defer cursor.Close(ctx)
var orders []entity.OrderPending
if err := cursor.All(ctx, &orders); err != nil {
return nil, err
}
return orders, nil
}
// UpdatePayInfo 更新支付信息(待支付订单)
func (d *OrderDao) UpdatePayInfo(ctx context.Context, tenantID, orderNo string, payInfo entity.PayInfo) error {
collection, err := d.getCollection(entity.OrderStatusPending)
if err != nil {
return err
}
_, err = collection.UpdateOne(ctx, bson.M{
"tenant_id": tenantID,
"order_no": orderNo,
}, bson.M{"$set": bson.M{
"pay_info": payInfo,
"updated_at": time.Now(),
}})
return err
}

229
dao/payment_dao.go Normal file
View File

@@ -0,0 +1,229 @@
package dao
import (
"context"
"errors"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"order/model/entity"
)
// PaymentConfigDao 支付配置数据访问对象
type PaymentConfigDao struct {
collection *mongo.Collection
}
// NewPaymentConfigDao 创建支付配置DAO实例
func NewPaymentConfigDao(collection *mongo.Collection) *PaymentConfigDao {
return &PaymentConfigDao{
collection: collection,
}
}
// Create 创建支付配置
func (d *PaymentConfigDao) Create(ctx context.Context, config *entity.PaymentConfig) error {
if d.collection == nil {
return errors.New("collection not initialized")
}
config.ID = primitive.NewObjectID()
_, err := d.collection.InsertOne(ctx, config)
return err
}
// GetByTenantAndMethod 根据租户和支付方式获取配置
func (d *PaymentConfigDao) GetByTenantAndMethod(ctx context.Context, tenantID, payMethod string) (*entity.PaymentConfig, error) {
if d.collection == nil {
return nil, errors.New("collection not initialized")
}
var config entity.PaymentConfig
err := d.collection.FindOne(ctx, bson.M{
"tenant_id": tenantID,
"pay_method": payMethod,
"enabled": true,
}).Decode(&config)
if err == mongo.ErrNoDocuments {
return nil, nil
}
return &config, err
}
// Update 更新支付配置
func (d *PaymentConfigDao) Update(ctx context.Context, id string, update bson.M) error {
if d.collection == nil {
return errors.New("collection not initialized")
}
objectID, err := primitive.ObjectIDFromHex(id)
if err != nil {
return err
}
_, err = d.collection.UpdateOne(ctx, bson.M{"_id": objectID}, bson.M{"$set": update})
return err
}
// ListByTenant 查询租户的支付配置列表
func (d *PaymentConfigDao) ListByTenant(ctx context.Context, tenantID string) ([]entity.PaymentConfig, error) {
if d.collection == nil {
return nil, errors.New("collection not initialized")
}
filter := bson.M{"tenant_id": tenantID}
cursor, err := d.collection.Find(ctx, filter)
if err != nil {
return nil, err
}
defer cursor.Close(ctx)
var configs []entity.PaymentConfig
if err := cursor.All(ctx, &configs); err != nil {
return nil, err
}
return configs, nil
}
// PaymentRecordDao 支付记录数据访问对象
type PaymentRecordDao struct {
collection *mongo.Collection
}
// NewPaymentRecordDao 创建支付记录DAO实例
func NewPaymentRecordDao(collection *mongo.Collection) *PaymentRecordDao {
return &PaymentRecordDao{
collection: collection,
}
}
// Create 创建支付记录
func (d *PaymentRecordDao) Create(ctx context.Context, record *entity.PaymentRecord) error {
if d.collection == nil {
return errors.New("collection not initialized")
}
record.ID = primitive.NewObjectID()
record.CreatedAt = time.Now().Unix()
record.UpdatedAt = time.Now().Unix()
_, err := d.collection.InsertOne(ctx, record)
return err
}
// GetByOrderNo 根据订单号获取支付记录
func (d *PaymentRecordDao) GetByOrderNo(ctx context.Context, tenantID, orderNo string) (*entity.PaymentRecord, error) {
if d.collection == nil {
return nil, errors.New("collection not initialized")
}
var record entity.PaymentRecord
err := d.collection.FindOne(ctx, bson.M{
"tenant_id": tenantID,
"order_no": orderNo,
}).Decode(&record)
if err == mongo.ErrNoDocuments {
return nil, nil
}
return &record, err
}
// UpdateStatus 更新支付记录状态
func (d *PaymentRecordDao) UpdateStatus(ctx context.Context, id string, status, transactionID, tradeNo string) error {
if d.collection == nil {
return errors.New("collection not initialized")
}
objectID, err := primitive.ObjectIDFromHex(id)
if err != nil {
return err
}
update := bson.M{
"status": status,
"transaction_id": transactionID,
"trade_no": tradeNo,
"updated_at": time.Now().Unix(),
}
_, err = d.collection.UpdateOne(ctx, bson.M{"_id": objectID}, bson.M{"$set": update})
return err
}
// RefundRecordDao 退款记录数据访问对象
type RefundRecordDao struct {
collection *mongo.Collection
}
// NewRefundRecordDao 创建退款记录DAO实例
func NewRefundRecordDao(collection *mongo.Collection) *RefundRecordDao {
return &RefundRecordDao{
collection: collection,
}
}
// Create 创建退款记录
func (d *RefundRecordDao) Create(ctx context.Context, record *entity.RefundRecord) error {
if d.collection == nil {
return errors.New("collection not initialized")
}
record.ID = primitive.NewObjectID()
record.CreatedAt = time.Now().Unix()
record.UpdatedAt = time.Now().Unix()
_, err := d.collection.InsertOne(ctx, record)
return err
}
// GetByRefundNo 根据退款单号获取退款记录
func (d *RefundRecordDao) GetByRefundNo(ctx context.Context, tenantID, refundNo string) (*entity.RefundRecord, error) {
if d.collection == nil {
return nil, errors.New("collection not initialized")
}
var record entity.RefundRecord
err := d.collection.FindOne(ctx, bson.M{
"tenant_id": tenantID,
"refund_no": refundNo,
}).Decode(&record)
if err == mongo.ErrNoDocuments {
return nil, nil
}
return &record, err
}
// UpdateRefundStatus 更新退款记录状态
func (d *RefundRecordDao) UpdateRefundStatus(ctx context.Context, id, status, refundID string) error {
if d.collection == nil {
return errors.New("collection not initialized")
}
objectID, err := primitive.ObjectIDFromHex(id)
if err != nil {
return err
}
update := bson.M{
"status": status,
"refund_id": refundID,
"updated_at": time.Now().Unix(),
}
_, err = d.collection.UpdateOne(ctx, bson.M{"_id": objectID}, bson.M{"$set": update})
return err
}