feat:新增订单发票,下单地址调整

This commit is contained in:
momo
2023-10-17 18:32:43 +08:00
parent 0310a6bd21
commit 6ae2cce870
23 changed files with 848 additions and 59 deletions

View File

@@ -8,9 +8,12 @@ import (
"fusenapi/constants"
"fusenapi/model/gmodel"
"fusenapi/utils/basic"
"fusenapi/utils/file"
"fusenapi/utils/handlers"
"fusenapi/utils/hash"
"fusenapi/utils/order"
"fusenapi/utils/pay"
"fusenapi/utils/pdf"
"fusenapi/utils/queue"
"math"
"time"
@@ -25,6 +28,7 @@ func NewOrder(gormDB *gorm.DB, awsSession *session.Session, delayQueue *queue.De
return &defaultOrder{
MysqlConn: gormDB,
DelayQueue: delayQueue,
AwsSession: awsSession,
}
}
@@ -32,6 +36,7 @@ type (
defaultOrder struct {
MysqlConn *gorm.DB
DelayQueue *queue.DelayMessage
AwsSession *session.Session
}
Order interface {
// 下单
@@ -44,6 +49,8 @@ type (
List(ctx context.Context, in *ListReq) (res *ListRes, err error)
// 详情
Detail(ctx context.Context, in *DetailReq) (res *DetailRes, err error)
// 发票
Invoice(ctx context.Context, in *InvoiceReq) (res *InvoiceRes, err error)
// 支付成功
PaymentSuccessful(ctx context.Context, in *PaymentSuccessfulReq) (res *PaymentSuccessfulRes, err error)
// 关闭
@@ -65,9 +72,14 @@ type (
}
OrderAddress struct {
Address string `json:"address"` // 详细地址
Mobile string `json:"mobile"` // 手机
Name string `json:"name"` // 姓
Street string `json:"street"` // 详细地址
City string `json:"city"` // 城市
FirstName string `json:"first_name"` // 姓
LastName string `json:"last_name"` // 名
Mobile string `json:"mobile"` // 手机
State string `json:"state"` // 州
Suite string `json:"suite"` // 房号
ZipCode string `json:"zip_code"` // 邮编号码
}
OrderPay struct {
ClientSecret string `json:"client_secret"` // 支付方--秘钥
@@ -85,6 +97,16 @@ type (
Amount int64 `json:"amount"` // 金额
Label string `json:"label"` // 标签
}
/* 发票 */
InvoiceReq struct {
UserId int64 `json:"user_id"`
OrderSn string `json:"order_sn"`
}
InvoiceRes struct {
ErrorCode basic.StatusResponse
InvoiceUrls []string `json:"invoice_urls"`
}
/* 发票 */
/* 删除订单 */
DeleteReq struct {
@@ -210,6 +232,292 @@ type (
/* 列表 */
)
// 订单发票
func (d *defaultOrder) Invoice(ctx context.Context, in *InvoiceReq) (res *InvoiceRes, err error) {
var errorCode basic.StatusResponse
var orderInfo gmodel.FsOrder
var receiptSnsResources []string
var receiptSnsDeposit string
var receiptSnsFinal string
var invoiceUrls []string
var orderTradeDeposit gmodel.FsOrderTrade
var orderTradeFinal gmodel.FsOrderTrade
model := d.MysqlConn.Where("is_del = ?", 0)
if in.UserId != 0 {
model = model.Where("user_id = ?", in.UserId)
}
if in.OrderSn != "" {
model = model.Where("order_sn = ?", in.OrderSn)
}
result := model.Take(&orderInfo)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
errorCode = *basic.CodeErrOrderCreatePrePaymentInfoNoFound
} else {
errorCode = *basic.CodeServiceErr
}
logc.Errorf(ctx, "order invoice detail failed, err: %v", err)
return &InvoiceRes{
ErrorCode: errorCode,
}, result.Error
}
if *orderInfo.PayStatus == int64(constants.ORDER_PAY_STATUS_PAIDDEPOSIT) || *orderInfo.PayStatus == int64(constants.ORDER_PAY_STATUS_PAIDDREMAINING) {
// 查询支付账单
var orderTradeList []gmodel.FsOrderTrade
model1 := d.MysqlConn
if in.OrderSn != "" {
model1 = model1.Where("order_sn = ?", in.OrderSn)
}
result1 := model1.Find(&orderTradeList)
if result1.Error != nil {
if errors.Is(result1.Error, gorm.ErrRecordNotFound) {
errorCode = *basic.CodeErrOrderCreatePrePaymentInfoNoFound
} else {
errorCode = *basic.CodeServiceErr
}
logc.Errorf(ctx, "order invoice trade failed, err: %v", err)
return &InvoiceRes{
ErrorCode: errorCode,
}, result1.Error
}
if len(orderTradeList) > 0 {
for _, orderTrade := range orderTradeList {
receiptSnsResources = append(receiptSnsResources, hash.JsonHashKey(*orderTrade.ReceiptSn))
if *orderTrade.PayStage == 1 {
receiptSnsDeposit = *orderTrade.ReceiptSn
orderTradeDeposit = orderTrade
}
if *orderTrade.PayStage == 2 {
receiptSnsFinal = *orderTrade.ReceiptSn
orderTradeFinal = orderTrade
}
}
// 查询支付账单
var resourceList []gmodel.FsResource
result2 := d.MysqlConn.Where("resource_id in ?", receiptSnsResources).Find(&resourceList)
if result2.Error != nil {
errorCode = *basic.CodeServiceErr
logc.Errorf(ctx, "order invoice esource failed, err: %v", err)
return &InvoiceRes{
ErrorCode: errorCode,
}, result1.Error
}
resourceListLen := len(resourceList)
for _, resource := range resourceList {
invoiceUrls = append(invoiceUrls, *resource.ResourceUrl)
}
if *orderInfo.PayStatus == int64(constants.ORDER_PAY_STATUS_PAIDDEPOSIT) {
if resourceListLen == 1 {
return &InvoiceRes{
ErrorCode: errorCode,
InvoiceUrls: invoiceUrls,
}, nil
}
if resourceListLen == 0 {
receiptSnsFinal = ""
}
}
if *orderInfo.PayStatus == int64(constants.ORDER_PAY_STATUS_PAIDDREMAINING) {
if resourceListLen == 2 {
return &InvoiceRes{
ErrorCode: errorCode,
InvoiceUrls: invoiceUrls,
}, nil
}
if resourceListLen == 1 {
receiptSnsDeposit = ""
}
}
} else {
errorCode = *basic.CodeErrOrderCreatePrePaymentInfoNoFound
return &InvoiceRes{
ErrorCode: errorCode,
}, errors.New("get order invoice failed, not found")
}
} else {
err = errors.New("get order invoice failed, pay status is illegality")
errorCode = *basic.CodeErrOrderInvoiceStatusIllegality
return &InvoiceRes{
ErrorCode: errorCode,
}, err
}
ress, err := d.OrderDetailHandler(ctx, &orderInfo, 1)
if err != nil {
logc.Errorf(ctx, "order invoice detail handler failed, err: %v", err)
errorCode = *basic.CodeServiceErr
return &InvoiceRes{
ErrorCode: errorCode,
}, err
} else {
var model001 = constants.INVOICE_TEMPLATE_01
var model002 string
var model003 string
var model004 string
var model005 string
var model006 = constants.INVOICE_TEMPLATE_06
// 生成收据发票--首款
ctimeDate := orderInfo.Ctime.Format("2006/01/02")
var name string
var city string
var street string
var state string
if ress.OrderDetail.DeliveryAddress != nil {
name = fmt.Sprintf("%s %s", ress.OrderDetail.DeliveryAddress.FirstName, ress.OrderDetail.DeliveryAddress.LastName)
street = ress.OrderDetail.DeliveryAddress.Street
city = ress.OrderDetail.DeliveryAddress.City
state = ress.OrderDetail.DeliveryAddress.State
}
var products string
for _, orderProduct := range ress.OrderDetail.OrderProduct {
var model00301 = constants.INVOICE_TEMPLATE_0301
var price = fmt.Sprintf("%s%s", constants.OrderCurrencyMessage[constants.Currency(orderProduct.ItemPrice.Current.CurrentCurrency)], orderProduct.ItemPrice.Current.CurrentAmount.(string))
var priceTotal = fmt.Sprintf("%s%s", constants.OrderCurrencyMessage[constants.Currency(orderProduct.TotalPrice.Current.CurrentCurrency)], orderProduct.TotalPrice.Current.CurrentAmount.(string))
var productsInfo = fmt.Sprintf(model00301, orderProduct.ProductName, price, orderProduct.PurchaseQuantity.Current, priceTotal)
products = products + productsInfo
}
model003 = fmt.Sprintf(constants.INVOICE_TEMPLATE_03, "", products)
var subtotal = fmt.Sprintf("%s%s", constants.OrderCurrencyMessage[constants.Currency(ress.OrderDetail.OrderAmount.Subtotal.Current.CurrentCurrency)], ress.OrderDetail.OrderAmount.Subtotal.Current.CurrentAmount.(string))
var taxStr = "0.00"
if ress.OrderDetail.OrderAmount.Tax.Current.CurrentAmount != nil {
taxStr = ress.OrderDetail.OrderAmount.Tax.Current.CurrentAmount.(string)
}
var taxCurrency string = constants.OrderCurrencyMessage[constants.Currency(ress.OrderDetail.OrderAmount.Tax.Current.CurrentCurrency)]
if taxCurrency == "" {
taxCurrency = constants.OrderCurrencyMessage[constants.Currency(ress.OrderDetail.OrderAmount.Total.Current.CurrentCurrency)]
}
var tax = fmt.Sprintf("%s%s", taxCurrency, taxStr)
var total = fmt.Sprintf("%s%s", constants.OrderCurrencyMessage[constants.Currency(ress.OrderDetail.OrderAmount.Total.Current.CurrentCurrency)], ress.OrderDetail.OrderAmount.Total.Current.CurrentAmount.(string))
if receiptSnsDeposit != "" {
v1 := receiptSnsDeposit
v2 := name
v3 := ctimeDate
v4 := street
v5 := city
v6 := state
model002 = fmt.Sprintf(constants.INVOICE_TEMPLATE_02, "", v1, v2, v3, v4, v5, v6)
v7 := "Deposit Requested"
v8 := fmt.Sprintf("%s%s", constants.OrderCurrencyMessage[constants.Currency(ress.OrderDetail.OrderAmount.Deposit.PayAmount.Current.CurrentCurrency)], ress.OrderDetail.OrderAmount.Deposit.PayAmount.Current.CurrentAmount.(string))
v9 := "Deposit Due"
v10 := v8
model004 = fmt.Sprintf(constants.INVOICE_TEMPLATE_04, "", subtotal, tax, total, v7, v8, v9, v10)
cardSn := "****" + *orderTradeDeposit.CardSn
model005 = fmt.Sprintf(constants.INVOICE_TEMPLATE_05, "", *orderTradeDeposit.CardBrand, cardSn)
var content = model001 + model002 + model003 + model004 + model005 + model006
base64, err := pdf.HtmlToPdfBase64(content, "html")
if err != nil {
logc.Errorf(ctx, "order invoice HtmlToPdfBase64 failed, err: %v", err)
errorCode = *basic.CodeServiceErr
return &InvoiceRes{
ErrorCode: errorCode,
}, err
}
// 根据hash 查询数据资源
var resourceId string = hash.JsonHashKey(receiptSnsDeposit)
// 上传文件
var upload = file.Upload{
Ctx: ctx,
MysqlConn: d.MysqlConn,
AwsSession: d.AwsSession,
}
uploadRes, err := upload.UploadFileByBase64(&file.UploadBaseReq{
FileHash: resourceId,
FileData: "data:application/pdf;base64," + base64,
UploadBucket: 1,
ApiType: 2,
UserId: *orderInfo.UserId,
GuestId: 0,
Source: "order_invoice",
Refresh: 1,
})
if err != nil {
if err != nil {
logc.Errorf(ctx, "order invoice UploadFileByBase64 failed, err: %v", err)
errorCode = *basic.CodeServiceErr
return &InvoiceRes{
ErrorCode: errorCode,
}, err
}
}
invoiceUrls = append(invoiceUrls, uploadRes.ResourceUrl)
}
// 生成收据发票--尾款
if receiptSnsFinal != "" {
v1 := receiptSnsFinal
v2 := name
v3 := ctimeDate
v4 := street
v5 := city
v6 := state
model002 = fmt.Sprintf(constants.INVOICE_TEMPLATE_02, "", v1, v2, v3, v4, v5, v6)
v7 := "Balance Requested"
v8 := fmt.Sprintf("%s%s", constants.OrderCurrencyMessage[constants.Currency(ress.OrderDetail.OrderAmount.RemainingBalance.PayAmount.Current.CurrentCurrency)], ress.OrderDetail.OrderAmount.RemainingBalance.PayAmount.Current.CurrentAmount.(string))
v9 := "Balance Due"
v10 := v8
model004 = fmt.Sprintf(constants.INVOICE_TEMPLATE_04, "", subtotal, tax, total, v7, v8, v9, v10)
cardSn := "****" + *orderTradeFinal.CardSn
model005 = fmt.Sprintf(constants.INVOICE_TEMPLATE_05, "", *orderTradeDeposit.CardBrand, cardSn)
var content = model001 + model002 + model003 + model004 + model005 + model006
base64, err := pdf.HtmlToPdfBase64(content, "html")
if err != nil {
logc.Errorf(ctx, "order invoice HtmlToPdfBase64 failed, err: %v", err)
errorCode = *basic.CodeServiceErr
return &InvoiceRes{
ErrorCode: errorCode,
}, err
}
// 根据hash 查询数据资源
var resourceId string = hash.JsonHashKey(receiptSnsDeposit)
// 上传文件
var upload = file.Upload{
Ctx: ctx,
MysqlConn: d.MysqlConn,
AwsSession: d.AwsSession,
}
uploadRes, err := upload.UploadFileByBase64(&file.UploadBaseReq{
FileHash: resourceId,
FileData: "data:application/pdf;base64," + base64,
UploadBucket: 1,
ApiType: 2,
UserId: *orderInfo.UserId,
GuestId: 0,
Source: "order_invoice",
Refresh: 1,
})
if err != nil {
if err != nil {
logc.Errorf(ctx, "order invoice UploadFileByBase64 failed, err: %v", err)
errorCode = *basic.CodeServiceErr
return &InvoiceRes{
ErrorCode: errorCode,
}, err
}
}
invoiceUrls = append(invoiceUrls, uploadRes.ResourceUrl)
}
return &InvoiceRes{
ErrorCode: errorCode,
InvoiceUrls: invoiceUrls,
}, nil
}
}
// 订单删除
func (d *defaultOrder) Delete(ctx context.Context, in *DeleteReq) (res *DeleteRes, err error) {
var errorCode basic.StatusResponse
@@ -626,6 +934,7 @@ func (d *defaultOrder) PaymentSuccessful(ctx context.Context, in *PaymentSuccess
}
// 新增交易信息
receiptSn := order.GenerateReceiptNumber()
tx.Create(&gmodel.FsOrderTrade{
UserId: orderInfo.UserId,
OrderSn: &orderSn,
@@ -642,6 +951,7 @@ func (d *defaultOrder) PaymentSuccessful(ctx context.Context, in *PaymentSuccess
Ctime: &ntime,
Utime: &ntime,
PayTitle: &payTitle,
ReceiptSn: &receiptSn,
})
// 更新数据库
@@ -818,9 +1128,14 @@ func (d *defaultOrder) CreatePrePaymentByDeposit(ctx context.Context, in *Create
if in.DeliveryMethod == constants.DELIVERYMETHODDIRECTMAIL && in.DeliveryAddress != nil {
orderAddress = &gmodel.OrderAddress{
Name: in.DeliveryAddress.Name,
Mobile: in.DeliveryAddress.Mobile,
Address: in.DeliveryAddress.Address,
Street: in.DeliveryAddress.Street,
City: in.DeliveryAddress.City,
FirstName: in.DeliveryAddress.FirstName,
LastName: in.DeliveryAddress.LastName,
Mobile: in.DeliveryAddress.Mobile,
State: in.DeliveryAddress.State,
Suite: in.DeliveryAddress.Suite,
ZipCode: in.DeliveryAddress.ZipCode,
}
orderAddressByte, err = json.Marshal(orderAddress)
if err != nil {
@@ -1101,8 +1416,14 @@ func (d *defaultOrder) Create(ctx context.Context, in *CreateReq) (res *CreateRe
// 直邮
if in.DeliveryMethod == constants.DELIVERYMETHODDIRECTMAIL {
orderAddress = &gmodel.OrderAddress{
Mobile: in.DeliveryAddress.Mobile,
Name: in.DeliveryAddress.Name,
Street: in.DeliveryAddress.Street,
City: in.DeliveryAddress.City,
FirstName: in.DeliveryAddress.FirstName,
LastName: in.DeliveryAddress.LastName,
Mobile: in.DeliveryAddress.Mobile,
State: in.DeliveryAddress.State,
Suite: in.DeliveryAddress.Suite,
ZipCode: in.DeliveryAddress.ZipCode,
}
}
// 预计交付时间