表结构

  1. package model
  2. import "time"
  3. type ShoppingCart struct{
  4. BaseModel
  5. User int32 `gorm:"type:int;index"`
  6. Goods int32 `gorm:"type:int;index"`
  7. Nums int32 `gorm:"type:int"`
  8. Checked bool
  9. }
  10. func (ShoppingCart) TableName() string {
  11. return "shoppingcart"
  12. }
  13. type OrderInfo struct{
  14. BaseModel
  15. User int32 `gorm:"type:int;index"`
  16. OrderSn string `gorm:"type:varchar(30);index"`
  17. PayType string `gorm:"type:varchar(20) comment 'alipay(支付宝), wechat(微信)'"`
  18. //status大家可以考虑使用iota来做
  19. Status string `gorm:"type:varchar(20) comment 'PAYING(待支付), TRADE_SUCCESS(成功), TRADE_SUCCESS(超时关闭), WAIT_BUYER_PAY(交易创建), TRADE_FINISHED(交易结束)'"`
  20. TradeNo string `gorm:"type:varchar(100) comment '交易号'"`
  21. OrderMount float32
  22. PayTime time.Time
  23. Address string `gorm:"type:varchar(100)"`
  24. SignerName string `gorm:"type:varchar(20)"`
  25. SingerMobile string `gorm:"type:varchar(11)"`
  26. Post string `gorm:"type:varchar(20)"`
  27. }
  28. func (OrderInfo) TableName() string {
  29. return "orderinfo"
  30. }
  31. type OrderGoods struct{
  32. BaseModel
  33. Order int32 `gorm:"type:int;index"`
  34. Goods int32 `gorm:"type:int;index"`
  35. GoodsName string `gorm:"type:varchar(100);index"`
  36. GoodsImage string `gorm:"type:varchar(200)"`
  37. GoodsPrice float32
  38. Nums int32 `gorm:"type:int"`
  39. }
  40. func (OrderGoods) TableName() string {
  41. return "ordergoods"
  42. }

proto文件定义


  1. syntax = "proto3";
  2. import "google/protobuf/empty.proto";
  3. option go_package = ".;proto";
  4. service Order {
  5. //购物车
  6. rpc CartItemList(UserInfo) returns(CartItemListResponse); //获取用户的购物车信息
  7. rpc CreateCartItem(CartItemRequest) returns(ShopCartInfoResponse); //添加商品到购物车
  8. rpc UpdateCartItem(CartItemRequest) returns(google.protobuf.Empty); //修改购物车记录
  9. //订单
  10. rpc Create(OrderRequest) returns (OrderInfoResponse); //创建订单
  11. rpc OrderList(OrderFilterRequest) returns (OrderListResponse); // 订单列表
  12. rpc OrderDetail(OrderRequest) returns (OrderInfoDetailResponse); // 订单详情
  13. rpc UpdateOrderStatus(OrderStatus) returns (google.protobuf.Empty); // 修改订单状态
  14. }
  15. message UserInfo {
  16. int32 id = 1;
  17. }
  18. message OrderStatus {
  19. int32 id = 1;
  20. string orderSn = 2;
  21. string status = 3;
  22. }
  23. message CartItemRequest {
  24. int32 id = 1;
  25. int32 userId = 2;
  26. int32 goodsId = 3;
  27. string goodsName = 4;
  28. string goodsImage = 5;
  29. float goodsPrice = 6;
  30. int32 nums = 7;
  31. bool checked = 8;
  32. }
  33. message OrderRequest {
  34. int32 id = 1;
  35. int32 userId = 2;
  36. string address = 3;
  37. string name = 4;
  38. string mobile = 5;
  39. string post = 6;
  40. }
  41. message OrderInfoResponse {
  42. int32 id = 1;
  43. int32 userId = 2;
  44. string orderSn = 3;
  45. string payType = 4;
  46. string status = 5;
  47. string post = 6;
  48. float total = 7;
  49. string address = 8;
  50. string name = 9;
  51. string mobile = 10;
  52. }
  53. message ShopCartInfoResponse {
  54. int32 id = 1;
  55. int32 userId = 2;
  56. int32 goodsId = 3;
  57. int32 nums = 4;
  58. bool checked = 5;
  59. }
  60. message OrderItemResponse {
  61. int32 id = 1;
  62. int32 orderId = 2;
  63. int32 goodsId = 3;
  64. string goodsName = 4;
  65. string goodsImage = 5;
  66. float goodsPrice = 6;
  67. int32 nums = 7;
  68. }
  69. message OrderInfoDetailResponse {
  70. OrderInfoResponse orderInfo = 1;
  71. repeated OrderItemResponse goods = 2;
  72. }
  73. message OrderFilterRequest {
  74. int32 userId = 1;
  75. int32 pages = 2;
  76. int32 pagePerNums = 3;
  77. }
  78. message OrderListResponse {
  79. int32 total = 1;
  80. repeated OrderInfoResponse data = 2;
  81. }
  82. message CartItemListResponse {
  83. int32 total = 1;
  84. repeated ShopCartInfoResponse data = 2;
  85. }

创建订单

  1. func (*OrderServer) CreateOrder(ctx context.Context, req *proto.OrderRequest) (*proto.OrderInfoResponse, error) {
  2. /*
  3. 新建订单
  4. 1. 从购物车中获取到选中的商品
  5. 2. 商品的价格自己查询 - 访问商品服务 (跨微服务)
  6. 3. 库存的扣减 - 访问库存服务 (跨微服务)
  7. 4. 订单的基本信息表 - 订单的商品信息表
  8. 5. 从购物车中删除已购买的记录
  9. */
  10. //定一个切片用来保存购物车商品数据
  11. var shopCarts []model.ShoppingCart
  12. //定义一个切片存放购物车下的商品id
  13. var goodsIds []int32
  14. //定义商品数据字典
  15. goodsNumsMap := make(map[int32]int32)
  16. if result := global.DB.Where(&model.ShoppingCart{User: req.UserId, Checked: true}).Find(&shopCarts); result.RowsAffected == 0 {
  17. return nil, status.Errorf(codes.Internal, "没有选中任何商品")
  18. }
  19. //得到购物车的所有商品id
  20. for _, shopCart := range shopCarts {
  21. goodsIds = append(goodsIds, shopCart.Goods)
  22. goodsNumsMap[shopCart.Goods] = shopCart.Nums
  23. }
  24. //去商品微服务查询商品价格
  25. goods, err := global.GoodsSrvClient.BatchGetGoods(context.Background(), &proto.BatchGoodsIdInfo{
  26. Id: goodsIds,
  27. })
  28. if err != nil {
  29. return nil, status.Errorf(codes.NotFound, "没有任何商品信息")
  30. }
  31. //订单的总金额 = 所有商品的金额加一起 (商品的价格(goods)*购物车商品的数量(shopCarts.nums))
  32. var orderMount float32
  33. //定义一个切片 保存扣减商品和数量信息
  34. var goodsInvInfo []*proto.GoodsInvInfo
  35. //定义一个切片 保存订单购买的所有商品
  36. var orderGoods []*model.OrderGoods
  37. for _, good := range goods.Data {
  38. orderMount += good.ShopPrice * float32(goodsNumsMap[good.Id])
  39. orderGoods = append(orderGoods, &model.OrderGoods{
  40. Goods: good.Id,
  41. GoodsName: good.Name,
  42. GoodsImage: good.GoodsFrontImage,
  43. GoodsPrice: good.ShopPrice,
  44. Nums: goodsNumsMap[good.Id],
  45. })
  46. goodsInvInfo = append(goodsInvInfo, &proto.GoodsInvInfo{
  47. GoodsId: good.Id,
  48. Num: goodsNumsMap[good.Id],
  49. })
  50. }
  51. //库存的扣减
  52. _, err = global.InventorySrvClient.Sell(context.Background(), &proto.SellInfo{
  53. GoodsInfo: goodsInvInfo,
  54. })
  55. if err != nil {
  56. return nil, status.Errorf(codes.NotFound, "库存扣减失败")
  57. }
  58. tx := global.DB.Begin()
  59. //创建订单基本信息表
  60. OrderInfo := model.OrderInfo{
  61. User: req.UserId,
  62. OrderSn: GenerateOrderSn(req.UserId),
  63. Status: "PAYING",
  64. OrderMount: orderMount,
  65. Address: req.Address,
  66. SignerName: req.Name,
  67. SingerMobile: req.Mobile,
  68. Post: req.Post,
  69. }
  70. if result := tx.Create(&OrderInfo); result.RowsAffected == 0 {
  71. tx.Rollback()
  72. return nil, status.Errorf(codes.Internal, "创建订单失败")
  73. }
  74. //创建订单商品表
  75. for _, orderGood := range orderGoods {
  76. orderGood.Order = OrderInfo.ID
  77. }
  78. //多条数据,最好不要循环入库,来使用批量入库
  79. if result := tx.CreateInBatches(orderGoods, 100); result.RowsAffected == 0 {
  80. tx.Rollback()
  81. return nil, status.Errorf(codes.Internal, "创建订单商品失败")
  82. }
  83. //从购物车中删除已购买的记录
  84. if result := tx.Where(&model.ShoppingCart{User: req.UserId, Checked: true}).Delete(&shopCarts); result.RowsAffected == 0 {
  85. tx.Rollback()
  86. return nil, status.Errorf(codes.Internal, "删除购物车商品失败")
  87. }
  88. //返回结果
  89. OrderInfoResponse := &proto.OrderInfoResponse{
  90. Id: OrderInfo.ID,
  91. UserId: OrderInfo.User,
  92. OrderSn: OrderInfo.OrderSn,
  93. PayType: OrderInfo.PayType,
  94. Status: OrderInfo.Status,
  95. Post: OrderInfo.Post,
  96. Total: OrderInfo.OrderMount,
  97. Address: OrderInfo.Address,
  98. Name: OrderInfo.SignerName,
  99. Mobile: OrderInfo.SingerMobile,
  100. AddTime: OrderInfo.CreatedAt.Format("2006-01-02 15:04:05"),
  101. }
  102. tx.Commit()
  103. return OrderInfoResponse, nil
  104. }