package repository import ( "context" "errors" "fmt" "time" "github.com/cloudprint/cloudprint-backend/internal/model" "gorm.io/gorm" ) type OrderRepository struct { db *gorm.DB } func NewOrderRepository(db *gorm.DB) *OrderRepository { return &OrderRepository{db: db} } func (r *OrderRepository) Create(ctx context.Context, order *model.Order) error { return r.db.WithContext(ctx).Create(order).Error } func (r *OrderRepository) CreateWithItems(ctx context.Context, order *model.Order, items []*model.OrderItem) error { return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { if err := tx.Create(order).Error; err != nil { return err } for _, item := range items { item.OrderID = order.ID if err := tx.Create(item).Error; err != nil { return err } } return nil }) } func (r *OrderRepository) GetByID(ctx context.Context, id int32) (*model.Order, error) { var order model.Order err := r.db.WithContext(ctx).Preload("Items").Preload("Items.File").Preload("Payment"). First(&order, id).Error if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, nil } return nil, err } return &order, nil } func (r *OrderRepository) GetByOrderNo(ctx context.Context, orderNo string) (*model.Order, error) { var order model.Order err := r.db.WithContext(ctx).Preload("Items").Preload("Items.File").Preload("Items.Printer").Preload("Payment"). Where("order_no = ?", orderNo).First(&order).Error if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, nil } return nil, err } return &order, nil } func (r *OrderRepository) GetListByUserID(ctx context.Context, userID int32, status int8, page, pageSize int) ([]*model.Order, int64, error) { var orders []*model.Order var total int64 query := r.db.WithContext(ctx).Model(&model.Order{}).Where("user_id = ?", userID) if status >= 0 { query = query.Where("status = ?", status) } err := query.Count(&total).Error if err != nil { return nil, 0, err } offset := (page - 1) * pageSize err = query.Preload("Items").Preload("Items.File"). Offset(offset).Limit(pageSize).Order("created_at DESC"). Find(&orders).Error if err != nil { return nil, 0, err } return orders, total, nil } func (r *OrderRepository) UpdateStatus(ctx context.Context, orderNo string, status int8) error { updates := map[string]interface{}{ "status": status, } if status == model.OrderStatusPaid { now := time.Now() updates["paid_at"] = &now } return r.db.WithContext(ctx).Model(&model.Order{}). Where("order_no = ?", orderNo).Updates(updates).Error } func (r *OrderRepository) GetStatistics(ctx context.Context) (totalUsers, totalOrders, todayOrders int64, todayRevenue float64, pendingOrders int64, err error) { // 总用户数 if err = r.db.WithContext(ctx).Model(&model.User{}).Count(&totalUsers).Error; err != nil { return 0, 0, 0, 0, 0, fmt.Errorf("count users failed: %w", err) } // 总订单数 if err = r.db.WithContext(ctx).Model(&model.Order{}).Count(&totalOrders).Error; err != nil { return 0, 0, 0, 0, 0, fmt.Errorf("count orders failed: %w", err) } // 待处理订单数 if err = r.db.WithContext(ctx).Model(&model.Order{}).Where("status IN ?", []int8{0, 1, 2}).Count(&pendingOrders).Error; err != nil { return 0, 0, 0, 0, 0, fmt.Errorf("count pending orders failed: %w", err) } // 今日订单数 today := time.Now().Format("2006-01-02") if err = r.db.WithContext(ctx).Model(&model.Order{}). Where("created_at::date = ? AND status = ?", today, model.OrderStatusPaid). Count(&todayOrders).Error; err != nil { return 0, 0, 0, 0, 0, fmt.Errorf("count today orders failed: %w", err) } // 今日收入 if err = r.db.WithContext(ctx).Model(&model.Order{}). Select("COALESCE(SUM(total_amount), 0)"). Where("created_at::date = ? AND status = ?", today, model.OrderStatusPaid). Scan(&todayRevenue).Error; err != nil { return 0, 0, 0, 0, 0, fmt.Errorf("sum today revenue failed: %w", err) } return } type OrderItemRepository struct { db *gorm.DB } func NewOrderItemRepository(db *gorm.DB) *OrderItemRepository { return &OrderItemRepository{db: db} } func (r *OrderItemRepository) GetByID(ctx context.Context, id int32) (*model.OrderItem, error) { var item model.OrderItem err := r.db.WithContext(ctx).Preload("File").First(&item, id).Error if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, nil } return nil, err } return &item, nil } func (r *OrderItemRepository) Create(ctx context.Context, item *model.OrderItem) error { return r.db.WithContext(ctx).Create(item).Error } func (r *OrderItemRepository) GetByOrderID(ctx context.Context, orderID int32) ([]*model.OrderItem, error) { var items []*model.OrderItem err := r.db.WithContext(ctx).Where("order_id = ?", orderID).Find(&items).Error return items, err }