package user import ( "bindbox-game/internal/repository/mysql/dao" "context" "fmt" ) // CancelShipping 取消发货申请 // 支持按单个资产ID取消,或按批次号批量取消 // 返回成功取消的记录数 func (s *service) CancelShipping(ctx context.Context, userID int64, inventoryID int64, batchNo string) (int64, error) { var cancelledCount int64 err := s.writeDB.Transaction(func(tx *dao.Query) error { var records []*struct { ID int64 InventoryID int64 } // 根据参数查询待取消的发货记录 if batchNo != "" { // 按批次号查询 rows, err := tx.ShippingRecords.WithContext(ctx). Select(tx.ShippingRecords.ID, tx.ShippingRecords.InventoryID). Where(tx.ShippingRecords.BatchNo.Eq(batchNo)). Where(tx.ShippingRecords.UserID.Eq(userID)). Where(tx.ShippingRecords.Status.Eq(1)). // 待发货状态 Find() if err != nil { return fmt.Errorf("query shipping records failed: %w", err) } for _, r := range rows { records = append(records, &struct { ID int64 InventoryID int64 }{ID: r.ID, InventoryID: r.InventoryID}) } } else if inventoryID > 0 { // 按单个资产ID查询 sr, err := tx.ShippingRecords.WithContext(ctx). Where(tx.ShippingRecords.InventoryID.Eq(inventoryID)). Where(tx.ShippingRecords.UserID.Eq(userID)). Where(tx.ShippingRecords.Status.Eq(1)). First() if err != nil { return fmt.Errorf("shipping record not found or already processed") } records = append(records, &struct { ID int64 InventoryID int64 }{ID: sr.ID, InventoryID: sr.InventoryID}) } if len(records) == 0 { return fmt.Errorf("no pending shipping records found") } // 批量处理每条记录 for _, rec := range records { // 更新发货记录状态为已取消 (status=5) if _, err := tx.ShippingRecords.WithContext(ctx). Where(tx.ShippingRecords.ID.Eq(rec.ID)). Update(tx.ShippingRecords.Status, 5); err != nil { return err } // 恢复库存状态为可用 (status=1) 并清空 shipping_no remark := fmt.Sprintf("|shipping_cancelled_by_user:%d", userID) if err := tx.UserInventory.WithContext(ctx).UnderlyingDB().Exec( "UPDATE user_inventory SET status=1, shipping_no='', remark=CONCAT(IFNULL(remark,''), ?) WHERE id=? AND user_id=?", remark, rec.InventoryID, userID, ).Error; err != nil { return err } cancelledCount++ } return nil }) if err != nil { return 0, err } return cancelledCount, nil }