package logic import ( "errors" "fmt" "fusenapi/model/gmodel" "fusenapi/utils/auth" "fusenapi/utils/basic" "fusenapi/utils/format" "fusenapi/utils/id_generator" "fusenapi/utils/step_price" "gorm.io/gorm" "math" "strings" "time" "context" "fusenapi/server/shopping-cart-confirmation/internal/svc" "fusenapi/server/shopping-cart-confirmation/internal/types" "github.com/zeromicro/go-zero/core/logx" ) type CreateOrderLogic struct { logx.Logger ctx context.Context svcCtx *svc.ServiceContext } func NewCreateOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateOrderLogic { return &CreateOrderLogic{ Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx, } } func (l *CreateOrderLogic) CreateOrder(req *types.CreateOrderReq, userinfo *auth.UserInfo) (resp *basic.Response) { if userinfo.GetIdType() != auth.IDTYPE_User { return resp.SetStatusWithMessage(basic.CodeUnAuth, "please login first") } if len(req.Form) == 0 { return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "err param form:can`t be empty") } cartIds := make([]int64, 0, len(req.Form)) mapForm := make(map[int64]int) for k, v := range req.Form { cartIds = append(cartIds, v.Id) mapForm[v.Id] = k } //获取购物车列表 cartList, err := l.svcCtx.AllModels.FsCart.GetUserCartsByIds(l.ctx, userinfo.UserId, cartIds) if err != nil { logx.Error(err) return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get cart list") } if len(cartList) != len(req.Form) { return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "sorry,may be some one not belong to you") } priceIds := make([]int64, 0, len(cartList)) optionalIds := make([]int64, 0, len(cartList)) for _, v := range cartList { priceIds = append(priceIds, *v.PriceId) optionalIds = append(optionalIds, *v.OptionalId) } //获取价格 priceList, err := l.svcCtx.AllModels.FsProductPrice.GetAllByIdsWithoutStatus(l.ctx, priceIds) if err != nil { logx.Error(err) return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product price list") } mapPrice := make(map[int64]int) for k, v := range priceList { mapPrice[v.Id] = k } //获取附加项 model3dList, err := l.svcCtx.AllModels.FsProductModel3d.GetAllByIdsWithoutStatus(l.ctx, optionalIds) if err != nil { logx.Error(err) return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get 3d model list") } mapModel3d := make(map[int64]int) for k, v := range model3dList { mapModel3d[v.Id] = k } var ( now = time.Now().Unix() total int64 //总价 ) orderSn := id_generator.GenSnNum() //开启事务 err = l.svcCtx.MysqlConn.Transaction(func(tx *gorm.DB) error { orderDetailTemplateModel := gmodel.NewFsOrderDetailTemplateModel(tx) orderDetailModel := gmodel.NewFsOrderDetailModel(tx) orderModel := gmodel.NewFsOrderModel(tx) //订单数据 deliveryMethod := int64(1) orderCreateData := gmodel.FsOrder{ Sn: &orderSn, UserId: &userinfo.UserId, Ctime: &now, Utime: &now, DeliveryMethod: &deliveryMethod, } if err = orderModel.Create(l.ctx, &orderCreateData); err != nil { return err } for _, cart := range cartList { priceIndex, ok := mapPrice[*cart.PriceId] if !ok { return errors.New(fmt.Sprintf("price info is not exists,id = %d", *cart.PriceId)) } //订单详情模板数据 orderDetailTemplateSn, err := id_generator.GenSnowFlakeId() if err != nil { return err } orderDetailTemplateCreateData := gmodel.FsOrderDetailTemplate{ Sn: &orderDetailTemplateSn, ProductId: cart.ProductId, ModelId: cart.OptionalId, TemplateId: cart.TemplateId, MaterialId: cart.MaterialId, SizeId: cart.SizeId, EachBoxNum: priceList[priceIndex].EachBoxNum, EachBoxWeight: priceList[priceIndex].EachBoxWeight, DesignId: cart.DesignId, Ctime: &now, } if err = orderDetailTemplateModel.Create(l.ctx, &orderDetailTemplateCreateData); err != nil { return err } //获取阶梯价格和数量 stepNumSlice, err := format.StrSlicToIntSlice(strings.Split(*priceList[priceIndex].StepNum, ",")) if err != nil { return err } stepPriceSlice, err := format.StrSlicToIntSlice(strings.Split(*priceList[priceIndex].StepPrice, ",")) if err != nil { return err } formIndex, _ := mapForm[cart.Id] //一定会有不用判断 //订单详情数据 orderDetailSn, err := id_generator.GenSnowFlakeId() if err != nil { return err } optionalPrice := int64(0) optionalTitle := "" if model3dIndex, ok := mapModel3d[*cart.OptionalId]; ok { optionalPrice = *model3dList[model3dIndex].Price optionalTitle = *model3dList[model3dIndex].Title } fn := int(math.Ceil(float64(req.Form[formIndex].Num) / float64(*priceList[priceIndex].EachBoxNum))) amount := step_price.GetCentStepPrice(fn, stepNumSlice, stepPriceSlice) orderDetailCreateData := gmodel.FsOrderDetail{ OrderId: &orderCreateData.Id, Sn: &orderDetailSn, UserId: &userinfo.UserId, OrderDetailTemplateId: &orderDetailTemplateCreateData.Id, ProductId: cart.ProductId, BuyNum: &req.Form[formIndex].Num, //以提交数量为准 Amount: &amount, Cover: cart.Cover, Ctime: &now, OptionalId: cart.OptionalId, OptionalTitle: &optionalTitle, OptionPrice: &optionalPrice, CartId: &cart.Id, } if err = orderDetailModel.Create(l.ctx, &orderDetailCreateData); err != nil { return err } total += amount * (*orderDetailCreateData.BuyNum) } //更新订单总价 return orderModel.Update(l.ctx, &gmodel.FsOrder{ Id: orderCreateData.Id, TotalAmount: &total, }) }) if err != nil { logx.Error(err) return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to create order") } return resp.SetStatusWithMessage(basic.CodeOK, "success", types.CreateOrderRsp{ Sn: orderSn, }) }