fusenapi/service/repositories/order.go

849 lines
28 KiB
Go
Raw Normal View History

2023-09-15 09:58:45 +00:00
package repositories
import (
"context"
"encoding/json"
"errors"
2023-09-21 11:01:48 +00:00
"fmt"
2023-09-19 11:17:04 +00:00
"fusenapi/constants"
2023-09-15 09:58:45 +00:00
"fusenapi/model/gmodel"
"fusenapi/utils/basic"
2023-09-21 11:01:48 +00:00
"fusenapi/utils/fssql"
"fusenapi/utils/handlers"
2023-09-18 07:39:12 +00:00
"fusenapi/utils/order"
2023-09-21 11:01:48 +00:00
"fusenapi/utils/pay"
2023-09-19 11:17:04 +00:00
"time"
2023-09-15 09:58:45 +00:00
"github.com/aws/aws-sdk-go/aws/session"
2023-09-20 10:04:33 +00:00
"github.com/zeromicro/go-zero/core/logx"
2023-09-15 09:58:45 +00:00
"gorm.io/gorm"
)
func NewOrder(gormDB *gorm.DB, bLMServiceUrl *string, awsSession *session.Session) Order {
return &defaultOrder{
MysqlConn: gormDB,
}
}
type (
defaultOrder struct {
MysqlConn *gorm.DB
}
Order interface {
// 下单
2023-09-20 07:07:12 +00:00
Create(ctx context.Context, in *CreateReq) (res *CreateRes, err error)
2023-09-21 11:01:48 +00:00
// 预支付--定金
CreatePrePaymentByDeposit(ctx context.Context, in *CreatePrePaymentByDepositReq) (res *CreatePrePaymentByDepositRes, err error)
2023-09-22 02:39:02 +00:00
// 预支付--定金
CreatePrePaymentByBalance(ctx context.Context, in *CreatePrePaymentByBalanceReq) (res *CreatePrePaymentByBalanceRes, err error)
2023-09-15 09:58:45 +00:00
// 列表
2023-09-21 11:01:48 +00:00
List(ctx context.Context, in *ListReq) (res *ListRes, err error)
2023-09-15 09:58:45 +00:00
// 详情
2023-09-21 02:30:36 +00:00
Detail(ctx context.Context, in *DetailReq) (res *DetailRes, err error)
2023-09-15 09:58:45 +00:00
}
2023-09-19 11:17:04 +00:00
OrderAddress struct {
Address string `json:"address"` // 详细地址
Mobile string `json:"mobile"` // 手机
Name string `json:"name"` // 姓名
}
2023-09-21 11:01:48 +00:00
OrderPay struct {
ClientSecret string `json:"client_secret"` // 支付方--秘钥
Country string `json:"country"` // 国家
Currency string `json:"currency"` // 货币
Metadata map[string]interface{} `json:"metadata"` // 额外参数
Method string `json:"method"` // 支付方--途径
OrderSn string `json:"order_sn"` // 订单编码
PayStage int64 `json:"pay_stage"` // 支付阶段
RedirectURL *string `json:"redirect_url"` // 支付方--重定向地址
Total OrderPayTotal `json:"total"` // 支付参数
}
// 支付参数
OrderPayTotal struct {
Amount int64 `json:"amount"` // 金额
Label string `json:"label"` // 标签
}
/* 预支付--定金 */
CreatePrePaymentByDepositReq struct {
StripeKey string `json:"stripe_key"`
Currency string `json:"currency"`
Country string `json:"country"`
UserId int64 `json:"user_id"`
OrderSn string `json:"order_sn"`
DeliveryMethod int64 `json:"delivery_method"`
2023-09-22 02:39:02 +00:00
DeliveryAddress *OrderAddress `json:"delivery_address"`
2023-09-21 11:01:48 +00:00
}
CreatePrePaymentByDepositRes struct {
ErrorCode basic.StatusResponse
OrderDetail gmodel.OrderDetail
OrderPay OrderPay
}
/* 预支付--定金 */
2023-09-19 11:17:04 +00:00
2023-09-22 02:39:02 +00:00
/* 预支付--尾款 */
CreatePrePaymentByBalanceReq struct {
2023-09-22 03:00:54 +00:00
StripeKey string `json:"stripe_key"`
Currency string `json:"currency"`
Country string `json:"country"`
UserId int64 `json:"user_id"`
OrderSn string `json:"order_sn"`
2023-09-22 02:39:02 +00:00
}
CreatePrePaymentByBalanceRes struct {
ErrorCode basic.StatusResponse
OrderDetail gmodel.OrderDetail
OrderPay OrderPay
}
/* 预支付--尾款 */
2023-09-15 09:58:45 +00:00
/* 下单 */
CreateReq struct {
2023-09-20 07:07:12 +00:00
ExpectedDeliveryTime time.Time `json:"expected_delivery_time"` // 预计到货时间
2023-09-19 11:17:04 +00:00
ExchangeRate int64 `json:"exchange_rate"` // 换算汇率(厘)
CurrentCurrency string `json:"current_currency"` // 当前货币
OriginalCurrency string `json:"original_currency"` // 原始货币
UserId int64 `json:"user_id"`
CartIds []int64 `json:"cart_ids"`
DeliveryMethod int64 `json:"delivery_method"`
DeliveryAddress *OrderAddress `json:"delivery_address"` // 收货地址
2023-09-15 09:58:45 +00:00
}
CreateRes struct {
ErrorCode basic.StatusResponse
OrderSn string
}
/* 下单 */
2023-09-21 02:30:36 +00:00
/* 详情 */
DetailReq struct {
UserId int64 `json:"user_id"`
OrderSn string `json:"order_sn"`
}
DetailRes struct {
2023-09-21 11:01:48 +00:00
ErrorCode basic.StatusResponse
OrderDetail gmodel.OrderDetail
OrderDetailOriginal gmodel.OrderDetail
2023-09-21 02:30:36 +00:00
}
/* 详情 */
2023-09-21 11:01:48 +00:00
/* 列表 */
ListReq struct {
UserId int64 `json:"user_id"`
DeliveryMethod int64 `json:"delivery_method"`
OrderCycle string `json:"order_cycle"`
CurrentPage int64 `json:"current_page"`
PerPage int64 `json:"per_page"`
}
ListRes struct {
OrderDetailList []gmodel.OrderDetail
Meta interface{}
}
/* 列表 */
2023-09-15 09:58:45 +00:00
)
2023-09-22 02:39:02 +00:00
// 预支付--尾款
func (d *defaultOrder) CreatePrePaymentByBalance(ctx context.Context, in *CreatePrePaymentByBalanceReq) (res *CreatePrePaymentByBalanceRes, err error) {
2023-09-22 03:00:54 +00:00
var errorCode basic.StatusResponse
var order gmodel.FsOrder
model := d.MysqlConn.Where("is_del = ?", 0)
if in.UserId != 0 {
model.Where("user_id = ?", in.UserId)
}
if in.OrderSn != "" {
model.Where("order_sn = ?", in.OrderSn)
}
result := model.Take(&order)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
errorCode = *basic.CodeErrOrderCreatePrePaymentInfoNoFound
} else {
errorCode = *basic.CodeServiceErr
}
logx.Errorf("create prePayment balance failed, err: %v", err)
return &CreatePrePaymentByBalanceRes{
ErrorCode: errorCode,
}, result.Error
}
// 非未支付
if *order.PayStatus != int64(constants.ORDERPAYSTATUSPAIDDEPOSIT) {
errorCode = *basic.CodeErrOrderCreatePrePaymentNoUnPaid
err = errors.New("order balance pay status is not unPaid")
logx.Errorf("create prePayment balance failed, err: %v", err)
return &CreatePrePaymentByBalanceRes{
ErrorCode: errorCode,
}, err
}
ress, err := d.OrderDetailHandler(ctx, &order)
if err != nil {
logx.Errorf("create prePayment balance failed DetailOrderDetailHandler, err: %v", err)
errorCode = *basic.CodeServiceErr
return &CreatePrePaymentByBalanceRes{
ErrorCode: errorCode,
}, err
}
// 支付初始化
amount := int64(ress.OrderDetailOriginal.OrderAmount.RemainingBalance.PayAmount.Current.CurrentAmount.(float64) / float64(10))
payConfig := &pay.Config{}
payConfig.Stripe.PayType = "intent"
payConfig.Stripe.Key = in.StripeKey
var generatePrepaymentReq = &pay.GeneratePrepaymentReq{
OrderSn: in.OrderSn,
ProductName: "支付尾款后期统一调整",
Amount: amount,
Currency: "usd",
Quantity: 1,
ProductDescription: "支付尾款后期统一调整",
}
payDriver := pay.NewPayDriver(1, payConfig)
prepaymentRes, err := payDriver.GeneratePrepayment(generatePrepaymentReq)
if err != nil {
logx.Errorf("create prePayment balance failed GeneratePrepayment, err: %v", err)
errorCode = *basic.CodeServiceErr
return &CreatePrePaymentByBalanceRes{
ErrorCode: errorCode,
}, nil
}
return &CreatePrePaymentByBalanceRes{
OrderDetail: ress.OrderDetail,
OrderPay: OrderPay{
ClientSecret: prepaymentRes.ClientSecret,
Country: in.Country,
Currency: in.Currency,
Method: payConfig.Stripe.PayType,
OrderSn: in.OrderSn,
PayStage: 1,
Total: OrderPayTotal{
Amount: amount,
Label: "支付尾款后期统一调整",
},
},
}, nil
2023-09-22 02:39:02 +00:00
}
2023-09-21 11:01:48 +00:00
// 预支付--定金
func (d *defaultOrder) CreatePrePaymentByDeposit(ctx context.Context, in *CreatePrePaymentByDepositReq) (res *CreatePrePaymentByDepositRes, err error) {
var errorCode basic.StatusResponse
2023-09-21 02:30:36 +00:00
var order gmodel.FsOrder
2023-09-21 11:01:48 +00:00
model := d.MysqlConn.Where("is_del = ?", 0)
if in.UserId != 0 {
model.Where("user_id = ?", in.UserId)
}
if in.OrderSn != "" {
model.Where("order_sn = ?", in.OrderSn)
}
result := model.Take(&order)
2023-09-21 02:30:36 +00:00
if result.Error != nil {
2023-09-21 11:01:48 +00:00
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
errorCode = *basic.CodeErrOrderCreatePrePaymentInfoNoFound
} else {
errorCode = *basic.CodeServiceErr
}
logx.Errorf("create prePayment deposit failed, err: %v", err)
return &CreatePrePaymentByDepositRes{
ErrorCode: errorCode,
}, result.Error
2023-09-21 02:30:36 +00:00
}
2023-09-21 11:01:48 +00:00
// 非未支付
if *order.PayStatus != int64(constants.ORDERPAYSTATUSUNPAIDDEPOSIT) {
2023-09-22 03:00:54 +00:00
errorCode = *basic.CodeErrOrderCreatePrePaymentNoUnPaid
2023-09-21 11:01:48 +00:00
err = errors.New("order pay status is not unPaidDeposit")
logx.Errorf("create prePayment deposit failed, err: %v", err)
return &CreatePrePaymentByDepositRes{
ErrorCode: errorCode,
}, err
}
// 是否超时支付
ntime := time.Now().UTC()
ctime := *order.Ctime
ctimeTimeOut := ctime.Add(30 * time.Minute).UTC().Unix()
ntimeTimeOut := ntime.Unix()
2023-09-22 03:00:54 +00:00
// 测试超时支付不限制
2023-09-21 11:01:48 +00:00
if ctimeTimeOut == ntimeTimeOut {
errorCode = *basic.CodeErrOrderCreatePrePaymentTimeout
err = errors.New("order pay timeout")
logx.Errorf("create prePayment deposit failed, err: %v", err)
return &CreatePrePaymentByDepositRes{
ErrorCode: errorCode,
}, err
}
2023-09-21 06:26:14 +00:00
ress, err := d.OrderDetailHandler(ctx, &order)
if err != nil {
2023-09-21 11:01:48 +00:00
logx.Errorf("create prePayment deposit failed DetailOrderDetailHandler, err: %v", err)
errorCode = *basic.CodeServiceErr
return &CreatePrePaymentByDepositRes{
ErrorCode: errorCode,
}, err
2023-09-21 06:26:14 +00:00
}
2023-09-21 11:01:48 +00:00
var uOrderDetail = make(map[string]interface{})
var orderAddress *gmodel.OrderAddress
if in.DeliveryAddress != nil {
if in.DeliveryAddress.Name != ress.OrderDetailOriginal.DeliveryAddress.Name || in.DeliveryAddress.Address != ress.OrderDetail.DeliveryAddress.Address || in.DeliveryAddress.Mobile != ress.OrderDetail.DeliveryAddress.Mobile {
orderAddress = &gmodel.OrderAddress{
Name: in.DeliveryAddress.Name,
Mobile: in.DeliveryAddress.Mobile,
Address: in.DeliveryAddress.Address,
}
}
}
var sql string = fmt.Sprintf(", `utime` = '%s'", ntime)
// 是否更新
if in.DeliveryMethod != *order.DeliveryMethod {
sql = sql + fmt.Sprintf(",`delivery_method` = %d", in.DeliveryMethod)
if in.DeliveryMethod == constants.DELIVERYMETHODDIRECTMAIL {
uOrderDetail["delivery_address"] = orderAddress
} else {
uOrderDetail["delivery_address"] = nil
}
uOrderDetail["order_info"] = struct {
DeliveryMethod int64 `json:"delivery_method"`
Utime *time.Time `json:"utime"`
}{
DeliveryMethod: in.DeliveryMethod,
Utime: &ntime,
}
} else {
if in.DeliveryMethod == constants.DELIVERYMETHODDIRECTMAIL {
// 更新收货地址
if orderAddress != nil {
uOrderDetail["delivery_address"] = orderAddress
uOrderDetail["order_info"] = struct {
DeliveryMethod int64 `json:"delivery_method"`
Utime *time.Time `json:"utime"`
}{
DeliveryMethod: in.DeliveryMethod,
Utime: &ntime,
}
}
}
}
2023-09-22 02:39:02 +00:00
if len(uOrderDetail) > 0 {
err = fssql.MetadataOrderPATCH(d.MysqlConn, sql, in.OrderSn, gmodel.FsOrder{}, uOrderDetail, "id = ?", order.Id)
if err != nil {
errorCode = *basic.CodeServiceErr
logx.Errorf("create prePayment deposit failed MetadataOrderPATCH, err: %v", err)
return &CreatePrePaymentByDepositRes{
ErrorCode: errorCode,
}, result.Error
}
}
ress.OrderDetail.OrderInfo.Utime = &ntime
ress.OrderDetail.OrderInfo.DeliveryMethod = in.DeliveryMethod
ress.OrderDetail.DeliveryAddress = orderAddress
2023-09-21 11:01:48 +00:00
// 支付初始化
amount := int64(ress.OrderDetailOriginal.OrderAmount.Deposit.PayAmount.Current.CurrentAmount.(float64) / float64(10))
payConfig := &pay.Config{}
payConfig.Stripe.PayType = "intent"
payConfig.Stripe.Key = in.StripeKey
var generatePrepaymentReq = &pay.GeneratePrepaymentReq{
OrderSn: in.OrderSn,
2023-09-22 03:00:54 +00:00
ProductName: "支付首款",
2023-09-21 11:01:48 +00:00
Amount: amount,
Currency: "usd",
Quantity: 1,
2023-09-22 03:00:54 +00:00
ProductDescription: "支付首款",
2023-09-21 11:01:48 +00:00
}
payDriver := pay.NewPayDriver(1, payConfig)
prepaymentRes, err := payDriver.GeneratePrepayment(generatePrepaymentReq)
if err != nil {
logx.Errorf("create prePayment deposit failed GeneratePrepayment, err: %v", err)
errorCode = *basic.CodeServiceErr
return &CreatePrePaymentByDepositRes{
ErrorCode: errorCode,
}, nil
}
return &CreatePrePaymentByDepositRes{
OrderDetail: ress.OrderDetail,
OrderPay: OrderPay{
ClientSecret: prepaymentRes.ClientSecret,
Country: in.Country,
Currency: in.Currency,
Method: payConfig.Stripe.PayType,
OrderSn: in.OrderSn,
PayStage: 1,
Total: OrderPayTotal{
Amount: amount,
Label: "",
},
},
2023-09-21 06:26:14 +00:00
}, nil
2023-09-21 02:30:36 +00:00
}
2023-09-21 11:01:48 +00:00
// 列表
func (d *defaultOrder) List(ctx context.Context, in *ListReq) (res *ListRes, err error) {
var orderList []gmodel.FsOrder
model := d.MysqlConn.Model(&gmodel.FsOrder{}).Where("is_del = ?", 0)
if in.UserId != 0 {
model.Where("user_id = ?", in.UserId)
}
2023-09-21 02:30:36 +00:00
2023-09-21 11:01:48 +00:00
// Where("pay_status > ?", 0)
if in.DeliveryMethod != 0 {
model.Where("delivery_method = ?", in.DeliveryMethod)
2023-09-21 02:30:36 +00:00
}
2023-09-21 11:01:48 +00:00
if in.OrderCycle != "" {
// 下单时间
switch in.OrderCycle {
case "within_one_month":
model.Where("ctime >?", time.Now().UTC().AddDate(0, -1, 0).Unix())
case "within_three_month":
model.Where("ctime >?", time.Now().UTC().AddDate(0, -3, 0).Unix())
case "within_six_month":
model.Where("ctime >?", time.Now().UTC().AddDate(0, -6, 0).Unix())
case "within_one_year":
model.Where("ctime >?", time.Now().UTC().AddDate(-1, 0, 0).Unix())
}
}
var count int64
resultCount := model.Count(&count)
if resultCount.Error != nil {
logx.Errorf("order count failed, err: %v", err)
return nil, resultCount.Error
}
var orderDetailList []gmodel.OrderDetail
if count > 0 {
m := model.Scopes(handlers.Paginate(&in.CurrentPage, &in.PerPage))
result := m.Find(&orderList)
if result.Error != nil {
logx.Errorf("order list failed, err: %v", err)
return nil, result.Error
}
for _, order := range orderList {
ress, err := d.OrderDetailHandler(ctx, &order)
if err != nil {
return nil, err
}
orderDetailList = append(orderDetailList, ress.OrderDetail)
}
} else {
orderDetailList = make([]gmodel.OrderDetail, 0)
}
return &ListRes{
OrderDetailList: orderDetailList,
Meta: map[string]int64{
"total_count": count,
"page_count": count / in.PerPage,
"current_page": in.CurrentPage,
"per_page": in.PerPage,
},
}, nil
}
// 详情
func (d *defaultOrder) Detail(ctx context.Context, in *DetailReq) (res *DetailRes, err error) {
var errorCode basic.StatusResponse
var order gmodel.FsOrder
model := d.MysqlConn.Where("is_del = ?", 0)
if in.UserId != 0 {
model.Where("user_id = ?", in.UserId)
}
if in.OrderSn != "" {
model.Where("order_sn = ?", in.OrderSn)
}
result := model.Take(&order)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
errorCode = *basic.CodeErrOrderCreatePrePaymentInfoNoFound
} else {
errorCode = *basic.CodeServiceErr
}
logx.Errorf("order detail failed, err: %v", err)
return &DetailRes{
ErrorCode: errorCode,
}, result.Error
}
// 是否超时支付
ctime := *order.Ctime
ctimeTimeOut := ctime.Add(30 * time.Minute).UTC().Unix()
ntimeTimeOut := time.Now().UTC().Unix()
if ctimeTimeOut < ntimeTimeOut {
errorCode = *basic.CodeErrOrderCreatePrePaymentTimeout
err = errors.New("order pay timeout")
logx.Errorf("order detail failed, err: %v", err)
return &DetailRes{
ErrorCode: errorCode,
}, err
}
ress, err := d.OrderDetailHandler(ctx, &order)
if err != nil {
logx.Errorf("order detail failed, err: %v", err)
errorCode = *basic.CodeServiceErr
return &DetailRes{
ErrorCode: errorCode,
}, err
2023-09-21 04:11:15 +00:00
}
2023-09-21 06:26:14 +00:00
return &DetailRes{
2023-09-21 11:01:48 +00:00
ErrorCode: errorCode,
OrderDetail: ress.OrderDetail,
2023-09-21 06:26:14 +00:00
}, nil
2023-09-21 02:30:36 +00:00
}
2023-09-15 09:58:45 +00:00
// 下单
func (d *defaultOrder) Create(ctx context.Context, in *CreateReq) (res *CreateRes, err error) {
var errorCode basic.StatusResponse
2023-09-20 03:39:56 +00:00
// 订单编号
2023-09-21 02:30:36 +00:00
var orderSn string = order.GenerateOrderNumber()
2023-09-20 03:39:56 +00:00
2023-09-15 09:58:45 +00:00
err = d.MysqlConn.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
// 查询购物车
var shoppingCartList []*gmodel.RelaFsShoppingCart
2023-09-20 10:04:33 +00:00
resShoppingCartFind := tx.Table(gmodel.NewFsShoppingCartModel(tx).TableName()).
Preload("ShoppingCartProduct", func(dbPreload *gorm.DB) *gorm.DB {
return dbPreload.Table(gmodel.NewFsProductModel(tx).TableName()).Preload("CoverResource")
}).Preload("ShoppingCartProductPriceList").
2023-09-20 07:10:18 +00:00
Preload("ShoppingCartProductModel3dList").
Preload("ShoppingCartProductModel3dFitting").
2023-09-15 09:58:45 +00:00
Where("id IN ?", in.CartIds).
Where("user_id = ?", in.UserId).
Find(&shoppingCartList)
err = resShoppingCartFind.Error
if err != nil {
return err
}
shoppingCartListLen := len(shoppingCartList)
if shoppingCartListLen == 0 {
errorCode = *basic.CodeErrOrderCreatShoppingCartEmpty
return errors.New(errorCode.Message)
}
if shoppingCartListLen != len(in.CartIds) {
errorCode = *basic.CodeErrOrderCreatShoppingCartNotMatched
return errors.New(errorCode.Message)
}
2023-09-18 07:39:12 +00:00
// 订单商品列表
2023-09-20 03:39:56 +00:00
var orderProductList []gmodel.OrderProduct
2023-09-15 09:58:45 +00:00
2023-09-18 07:39:12 +00:00
var shippingFee gmodel.AmountInfo
// 订单税费总价(厘)
var shippingFeeTotal int64
var tax = gmodel.AmountInfo{}
// 订单邮费总价(厘)
var taxTotal int64
var discount gmodel.AmountInfo
// 订单折扣总价(厘)
var discountTotal int64
var subtotal gmodel.AmountInfo
// 订单商品总价(厘)
var orderProductTotal int64
var total gmodel.AmountInfo
// 订单总价(厘)
var orderTotal int64
2023-09-19 11:17:04 +00:00
var nowTime = time.Now().UTC()
// 收货地址
var orderAddress *gmodel.OrderAddress
// 支付状态
var payStatus = constants.ORDERPAYSTATUSUNPAIDDEPOSIT
// 直邮
if in.DeliveryMethod == constants.DELIVERYMETHODDIRECTMAIL {
orderAddress = &gmodel.OrderAddress{
Mobile: in.DeliveryAddress.Mobile,
Name: in.DeliveryAddress.Name,
}
}
2023-09-19 05:56:59 +00:00
2023-09-15 09:58:45 +00:00
for _, shoppingCart := range shoppingCartList {
// 购物车快照
2023-09-20 07:28:57 +00:00
var shoppingCartSnapshot gmodel.CartSnapshot
2023-09-15 09:58:45 +00:00
// 购物车商品价格
var shoppingCartProductPrice *gmodel.FsProductPrice
// 购物车商品模型
var shoppingCartProductModel3d *gmodel.FsProductModel3d
if shoppingCart.Snapshot != nil {
json.Unmarshal([]byte(*shoppingCart.Snapshot), &shoppingCartSnapshot)
}
// 商品异常
if shoppingCart.ShoppingCartProduct == nil || (shoppingCart.ShoppingCartProduct != nil && *shoppingCart.ShoppingCartProduct.IsShelf == 0) {
errorCode = *basic.CodeErrOrderCreatProductAbsent
2023-09-15 10:30:45 +00:00
errorCode.Message = "create order failed, product '" + shoppingCartSnapshot.ProductInfo.ProductName + "'is absent"
2023-09-15 09:58:45 +00:00
return errors.New(errorCode.Message)
}
// 商品价格异常
if len(shoppingCart.ShoppingCartProductPriceList) == 0 {
errorCode = *basic.CodeErrOrderCreatProductPriceAbsent
2023-09-15 10:30:45 +00:00
errorCode.Message = "create order failed, price of product '" + shoppingCartSnapshot.ProductInfo.ProductName + "'is absent"
2023-09-15 09:58:45 +00:00
return errors.New(errorCode.Message)
} else {
var isProductPrice bool
for _, shoppingCartProductPriceInfo := range shoppingCart.ShoppingCartProductPriceList {
2023-09-20 10:04:33 +00:00
if *shoppingCart.SizeId == *shoppingCartProductPriceInfo.SizeId {
2023-09-15 09:58:45 +00:00
shoppingCartProductPrice = shoppingCartProductPriceInfo
isProductPrice = true
break
}
}
if !isProductPrice {
errorCode = *basic.CodeErrOrderCreatProductPriceAbsent
2023-09-15 10:30:45 +00:00
errorCode.Message = "create order failed, price of product '" + shoppingCartSnapshot.ProductInfo.ProductName + "'is absent"
2023-09-15 09:58:45 +00:00
return errors.New(errorCode.Message)
}
shoppingCart.ShoppingCartProductPriceList = []*gmodel.FsProductPrice{shoppingCartProductPrice}
}
// 商品模型异常
if len(shoppingCart.ShoppingCartProductModel3dList) == 0 {
errorCode = *basic.CodeErrOrderCreatProductAccessoryAbsent
2023-09-15 10:30:45 +00:00
errorCode.Message = "create order failed, accessoryof product '" + shoppingCartSnapshot.ProductInfo.ProductName + "'is absent"
2023-09-15 09:58:45 +00:00
return errors.New(errorCode.Message)
} else {
var isProductModel bool
for _, shoppingCartProductModel3dInfo := range shoppingCart.ShoppingCartProductModel3dList {
2023-09-20 10:04:33 +00:00
if *shoppingCart.SizeId == *shoppingCartProductModel3dInfo.SizeId {
2023-09-15 09:58:45 +00:00
shoppingCartProductModel3d = shoppingCartProductModel3dInfo
isProductModel = true
break
}
}
if !isProductModel {
errorCode = *basic.CodeErrOrderCreatProductAccessoryAbsent
2023-09-15 10:30:45 +00:00
errorCode.Message = "create order failed, accessory of product '" + shoppingCartSnapshot.ProductInfo.ProductName + "'is absent"
2023-09-15 09:58:45 +00:00
return errors.New(errorCode.Message)
}
shoppingCart.ShoppingCartProductModel3dList = []*gmodel.FsProductModel3d{shoppingCartProductModel3d}
}
2023-09-15 10:30:45 +00:00
var stepNum []int
var stepPrice []int
if *shoppingCartProductPrice.StepNum == "" {
errorCode = *basic.CodeErrOrderCreatProductPriceAbsent
errorCode.Message = "create order failed, step num of product '" + shoppingCartSnapshot.ProductInfo.ProductName + "'is failed"
return errors.New(errorCode.Message)
} else {
json.Unmarshal([]byte(*shoppingCartProductPrice.StepNum), &stepNum)
}
if *shoppingCartProductPrice.StepPrice == "" {
errorCode = *basic.CodeErrOrderCreatProductPriceAbsent
errorCode.Message = "create order failed, step price of product '" + shoppingCartSnapshot.ProductInfo.ProductName + "'is failed"
return errors.New(errorCode.Message)
} else {
json.Unmarshal([]byte(*shoppingCartProductPrice.StepPrice), &stepPrice)
}
2023-09-20 03:57:08 +00:00
/* 计算价格 */
2023-09-20 08:21:06 +00:00
productPrice, productTotalPrice, stepNum, stepPrice, err := NewShoppingCart(tx, nil, nil).CaculateCartPrice(*shoppingCart.PurchaseQuantity, shoppingCartProductPrice, *shoppingCart.ShoppingCartProductModel3dFitting.Price)
2023-09-20 03:55:51 +00:00
if err != nil {
errorCode = *basic.CodeErrOrderCreatProductPriceAbsent
2023-09-20 08:21:06 +00:00
errorCode.Message = "create order failed, step price of product '" + shoppingCartSnapshot.ProductInfo.ProductName + "'is failed"
return err
2023-09-20 03:55:51 +00:00
}
2023-09-20 03:57:08 +00:00
/* 计算价格 */
2023-09-18 07:39:12 +00:00
// 订单商品总价(厘)
orderProductTotal = orderProductTotal + productTotalPrice
// 订单商品
2023-09-20 07:07:12 +00:00
var productCoverMetadata map[string]interface{}
if shoppingCart.ShoppingCartProduct.CoverResource != nil && shoppingCart.ShoppingCartProduct.CoverResource.Metadata != nil {
json.Unmarshal(*shoppingCart.ShoppingCartProduct.CoverResource.Metadata, &productCoverMetadata)
}
2023-09-20 03:39:56 +00:00
orderProductList = append(orderProductList, gmodel.OrderProduct{
2023-09-20 07:07:12 +00:00
TotalPrice: order.GetAmountInfo(order.GetAmountInfoReq{
2023-09-18 07:39:12 +00:00
ExchangeRate: in.ExchangeRate,
Initiate: productTotalPrice,
Current: productTotalPrice,
CurrentCurrency: in.CurrentCurrency,
OriginalCurrency: in.OriginalCurrency,
}),
2023-09-20 10:04:33 +00:00
ExpectedDeliveryTime: &in.ExpectedDeliveryTime,
2023-09-20 07:07:12 +00:00
PurchaseQuantity: *shoppingCart.PurchaseQuantity,
2023-09-18 07:39:12 +00:00
ProductID: *shoppingCart.ProductId,
2023-09-20 07:07:12 +00:00
ProductCover: *shoppingCart.ShoppingCartProduct.Cover,
ProductCoverMetadata: productCoverMetadata,
2023-09-18 07:39:12 +00:00
ProductName: *shoppingCart.ShoppingCartProduct.Title,
2023-09-20 07:07:12 +00:00
ItemPrice: order.GetAmountInfo(order.GetAmountInfoReq{
2023-09-18 07:39:12 +00:00
ExchangeRate: in.ExchangeRate,
Initiate: productPrice,
Current: productPrice,
CurrentCurrency: in.CurrentCurrency,
OriginalCurrency: in.OriginalCurrency,
}),
2023-09-20 10:04:33 +00:00
ProductSnapshot: shoppingCart.ShoppingCartProduct,
2023-09-20 07:37:22 +00:00
ShoppingCartSnapshot: &shoppingCart.FsShoppingCart,
2023-09-20 07:07:12 +00:00
ProductSn: *shoppingCart.ShoppingCartProduct.Sn,
2023-09-20 07:39:23 +00:00
DiyInformation: &shoppingCartSnapshot.UserDiyInformation,
2023-09-20 08:37:37 +00:00
FittingInfo: &gmodel.OrderProductFittingInfo{
FittingID: *shoppingCart.FittingId,
FittingName: shoppingCartSnapshot.FittingInfo.FittingName,
},
SizeInfo: &gmodel.OrderProductSizeInfo{
SizeID: *shoppingCart.SizeId,
Capacity: shoppingCartSnapshot.SizeInfo.Capacity,
Title: gmodel.OrderProductSizeInfoTitle{
Inch: shoppingCartSnapshot.SizeInfo.Inch,
Cm: shoppingCartSnapshot.SizeInfo.Cm,
},
},
2023-09-21 04:11:15 +00:00
StepNum: stepNum,
IsHighlyCustomized: *shoppingCart.IsHighlyCustomized,
2023-09-18 07:39:12 +00:00
})
2023-09-15 09:58:45 +00:00
}
2023-09-18 07:39:12 +00:00
subtotal = order.GetAmountInfo(order.GetAmountInfoReq{
ExchangeRate: in.ExchangeRate,
Initiate: orderProductTotal,
Current: orderProductTotal,
CurrentCurrency: in.CurrentCurrency,
OriginalCurrency: in.OriginalCurrency,
})
orderTotal = orderProductTotal + shippingFeeTotal + taxTotal - discountTotal
total = order.GetAmountInfo(order.GetAmountInfoReq{
ExchangeRate: in.ExchangeRate,
Initiate: orderTotal,
Current: orderTotal,
CurrentCurrency: in.CurrentCurrency,
OriginalCurrency: in.OriginalCurrency,
})
2023-09-19 11:17:04 +00:00
// 定金
2023-09-20 03:39:56 +00:00
var depositInt int64 = orderTotal / 2
2023-09-19 11:17:04 +00:00
var deposit = gmodel.PayInfo{
Status: gmodel.PayStatus{
StatusCode: int64(constants.PAYSTATUSUNPAID),
StatusTitle: constants.PayStatusMessage[constants.PAYSTATUSUNPAID],
},
2023-09-20 03:39:56 +00:00
PayAmount: order.GetAmountInfo(order.GetAmountInfoReq{
ExchangeRate: in.ExchangeRate,
Initiate: depositInt,
Current: depositInt,
CurrentCurrency: in.CurrentCurrency,
OriginalCurrency: in.OriginalCurrency,
}),
2023-09-19 11:17:04 +00:00
}
2023-09-18 07:39:12 +00:00
2023-09-19 11:17:04 +00:00
// 尾款
2023-09-20 03:39:56 +00:00
var remainingBalanceInt int64 = orderTotal - depositInt
var remainingBalance = gmodel.PayInfo{
Status: gmodel.PayStatus{
StatusCode: int64(constants.PAYSTATUSUNPAID),
StatusTitle: constants.PayStatusMessage[constants.PAYSTATUSUNPAID],
},
PayAmount: order.GetAmountInfo(order.GetAmountInfoReq{
ExchangeRate: in.ExchangeRate,
Initiate: remainingBalanceInt,
Current: remainingBalanceInt,
CurrentCurrency: in.CurrentCurrency,
OriginalCurrency: in.OriginalCurrency,
}),
}
2023-09-19 11:17:04 +00:00
var orderAmount = gmodel.OrderAmount{
Deposit: deposit,
RemainingBalance: remainingBalance,
2023-09-20 03:39:56 +00:00
Discount: discount,
ShippingFee: shippingFee,
Tax: tax,
Subtotal: subtotal,
Total: total,
}
// 订单状态--当前
var status = gmodel.OrderStatus{
2023-09-20 10:04:33 +00:00
Ctime: &nowTime,
Utime: &nowTime,
2023-09-20 03:39:56 +00:00
StatusCode: constants.ORDERSTATUSUNPAIDDEPOSIT,
StatusTitle: constants.OrderStatusMessage[constants.ORDERSTATUSUNPAIDDEPOSIT],
}
// 订单状态--链路
2023-09-20 07:07:12 +00:00
var statusLink = order.GenerateOrderStatusLink(in.DeliveryMethod, nowTime, in.ExpectedDeliveryTime)
2023-09-20 03:39:56 +00:00
var orderInfo = gmodel.OrderInfo{
2023-09-20 10:04:33 +00:00
Ctime: &nowTime,
2023-09-20 03:39:56 +00:00
DeliveryMethod: in.DeliveryMethod,
OrderSn: orderSn,
Status: status,
StatusLink: statusLink,
}
var orderDetail = gmodel.OrderDetail{
DeliveryAddress: orderAddress,
OrderAmount: orderAmount,
OrderInfo: orderInfo,
OrderProduct: orderProductList,
PayStatus: payStatus,
2023-09-21 11:01:48 +00:00
PayTimeout: 30 * time.Minute,
2023-09-20 03:39:56 +00:00
}
// 数据库操作
2023-09-20 10:04:33 +00:00
orderDetailByte, err := json.Marshal(orderDetail)
if err != nil {
return err
}
var order = gmodel.FsOrder{
2023-09-20 03:39:56 +00:00
UserId: &in.UserId,
DeliveryMethod: &in.DeliveryMethod,
OrderSn: &orderSn,
Status: (*int64)(&status.StatusCode),
PayStatus: (*int64)(&payStatus),
Ctime: &nowTime,
2023-09-20 10:04:33 +00:00
Metadata: &orderDetailByte,
2023-09-20 03:39:56 +00:00
}
result := tx.Create(&order)
if result.Error != nil {
return result.Error
2023-09-19 11:17:04 +00:00
}
2023-09-15 09:58:45 +00:00
return nil
})
if err != nil {
2023-09-21 11:01:48 +00:00
logx.Errorf("order create order failed, err: %v", err)
2023-09-20 10:04:33 +00:00
if errorCode.Code == 0 {
errorCode.Code = basic.CodeApiErr.Code
errorCode.Message = basic.CodeApiErr.Message
}
2023-09-20 03:39:56 +00:00
return &CreateRes{
OrderSn: orderSn,
ErrorCode: errorCode,
}, err
2023-09-15 09:58:45 +00:00
}
return &CreateRes{
2023-09-20 03:39:56 +00:00
OrderSn: orderSn,
2023-09-15 09:58:45 +00:00
ErrorCode: errorCode,
}, nil
}
2023-09-21 11:01:48 +00:00
// 详情处理
func (d *defaultOrder) OrderDetailHandler(ctx context.Context, orderInfo *gmodel.FsOrder) (res *DetailRes, err error) {
var orderDetail gmodel.OrderDetail
err = json.Unmarshal(*orderInfo.Metadata, &orderDetail)
if err != nil {
logx.Errorf("order detail handler unmarshal metadata failed, err: %v", err)
return nil, err
}
orderDetailOriginal := orderDetail
for orderProductKey, orderProduct := range orderDetail.OrderProduct {
orderDetail.OrderProduct[orderProductKey].TotalPrice = order.GetAmountInfoFormat(&orderProduct.TotalPrice)
orderDetail.OrderProduct[orderProductKey].ItemPrice = order.GetAmountInfoFormat(&orderProduct.ItemPrice)
orderDetail.OrderProduct[orderProductKey].ShoppingCartSnapshot = nil
orderDetail.OrderProduct[orderProductKey].ProductSnapshot = nil
}
orderDetail.OrderInfo.StatusLink = order.GetOrderStatusLinkUser(orderDetail.OrderInfo.DeliveryMethod, orderDetail.OrderInfo.StatusLink)
orderDetail.OrderAmount.Deposit.PayAmount = order.GetAmountInfoFormat(&orderDetail.OrderAmount.Deposit.PayAmount)
orderDetail.OrderAmount.RemainingBalance.PayAmount = order.GetAmountInfoFormat(&orderDetail.OrderAmount.RemainingBalance.PayAmount)
orderDetail.OrderAmount.Subtotal = order.GetAmountInfoFormat(&orderDetail.OrderAmount.Subtotal)
orderDetail.OrderAmount.Total = order.GetAmountInfoFormat(&orderDetail.OrderAmount.Total)
orderDetail.PayTimeout = time.Duration(orderDetail.OrderInfo.Ctime.Add(orderDetail.PayTimeout).UTC().Unix() - time.Now().UTC().Unix())
return &DetailRes{
OrderDetail: orderDetail,
OrderDetailOriginal: orderDetailOriginal,
}, nil
}