187 lines
7.3 KiB
Go
187 lines
7.3 KiB
Go
package logic
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"fusenapi/constants"
|
|
"fusenapi/model/gmodel"
|
|
"fusenapi/utils/auth"
|
|
"fusenapi/utils/basic"
|
|
"fusenapi/utils/pdf"
|
|
"strings"
|
|
"time"
|
|
|
|
"context"
|
|
|
|
"fusenapi/server/orders/internal/svc"
|
|
"fusenapi/server/orders/internal/types"
|
|
|
|
"github.com/zeromicro/go-zero/core/logx"
|
|
)
|
|
|
|
type GetOrderInvoiceLogic struct {
|
|
logx.Logger
|
|
ctx context.Context
|
|
svcCtx *svc.ServiceContext
|
|
}
|
|
|
|
func NewGetOrderInvoiceLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetOrderInvoiceLogic {
|
|
return &GetOrderInvoiceLogic{
|
|
Logger: logx.WithContext(ctx),
|
|
ctx: ctx,
|
|
svcCtx: svcCtx,
|
|
}
|
|
}
|
|
|
|
func (l *GetOrderInvoiceLogic) GetOrderInvoice(req *types.GetOrderInvoiceReq, userinfo *auth.UserInfo) (resp *basic.Response) {
|
|
if userinfo.GetIdType() != auth.IDTYPE_User {
|
|
return resp.SetStatusWithMessage(basic.CodeUnAuth, "please login first")
|
|
}
|
|
//获取用户信息
|
|
userModel := gmodel.NewFsUserModel(l.svcCtx.MysqlConn)
|
|
user, err := userModel.FindUserById(l.ctx, userinfo.UserId)
|
|
if err != nil {
|
|
logx.Error(err)
|
|
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get user info")
|
|
}
|
|
if user.Id == 0 {
|
|
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "user not found")
|
|
}
|
|
if req.Sn == "" {
|
|
return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "param sn is required")
|
|
}
|
|
//查询订单信息
|
|
orderModel := gmodel.NewFsOrderModel(l.svcCtx.MysqlConn)
|
|
orderInfo, err := orderModel.FindOneBySn(l.ctx, userinfo.UserId, req.Sn)
|
|
if err != nil {
|
|
logx.Error(err)
|
|
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get order info")
|
|
}
|
|
if orderInfo.Id == 0 {
|
|
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "order is not exists")
|
|
}
|
|
//地址数据
|
|
var address gmodel.FsAddress
|
|
if err = json.Unmarshal([]byte(*orderInfo.AddressInfo), &address); err != nil {
|
|
logx.Error(err)
|
|
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to parse address info")
|
|
}
|
|
userName := ""
|
|
if user.LastName != nil && user.FirstName != nil && *user.LastName != "" && *user.FirstName != "" {
|
|
userName = *user.LastName + " " + *user.FirstName
|
|
} else if address.LastName != nil && address.FirstName != nil && *address.LastName != "" && *address.FirstName != "" {
|
|
userName = *address.LastName + " " + *address.LastName
|
|
}
|
|
pdfFileName := *orderInfo.Sn + "_" + userName + "_FusenPack.pdf"
|
|
//首款
|
|
firstPayment := *orderInfo.TotalAmount / 2
|
|
amountDue := int64(0)
|
|
//未完全支付
|
|
if *orderInfo.IsPayCompleted == 0 {
|
|
amountDue = *orderInfo.TotalAmount - firstPayment
|
|
}
|
|
var (
|
|
secondPaymentHtml string
|
|
firstStyle1 = `style="padding-bottom: 20px; border-bottom: 1px solid #212121;"`
|
|
firstStyle2 = `style="width: 16.66%; padding-bottom: 20px; border-bottom: 1px solid #212121;"`
|
|
payHtml = strings.Builder{}
|
|
orderHTML strings.Builder
|
|
totalAmount float64
|
|
rowspan = `rowspan = "12"`
|
|
)
|
|
if *orderInfo.IsPayCompleted == 1 {
|
|
firstStyle1 = ""
|
|
firstStyle2 = ""
|
|
rowspan = `rowspan = "14"`
|
|
remainAmount := float64(*orderInfo.TotalAmount - firstPayment)
|
|
secondPaymentHtml = strings.ReplaceAll(constants.SECOND_PAYMENY_HTML, "{{remain_amount}}", fmt.Sprintf("%.2f", remainAmount/100))
|
|
}
|
|
//获取订单详情列表
|
|
orderDetailModel := gmodel.NewFsOrderDetailModel(l.svcCtx.MysqlConn)
|
|
orderDetails, err := orderDetailModel.GetOrderDetailsByOrderId(l.ctx, orderInfo.Id)
|
|
if err != nil {
|
|
logx.Error(err)
|
|
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get order details")
|
|
}
|
|
if len(orderDetails) == 0 {
|
|
return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "order details is empty")
|
|
}
|
|
productIds := make([]int64, 0, len(orderDetails))
|
|
for _, v := range orderDetails {
|
|
productIds = append(productIds, *v.ProductId)
|
|
}
|
|
//获取产品列表
|
|
productModel := gmodel.NewFsProductModel(l.svcCtx.MysqlConn)
|
|
productList, err := productModel.GetProductListByIds(l.ctx, productIds, "")
|
|
if err != nil {
|
|
logx.Error(err)
|
|
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get product list")
|
|
}
|
|
mapProduct := make(map[int64]int)
|
|
for k, v := range productList {
|
|
mapProduct[v.Id] = k
|
|
}
|
|
payModel := gmodel.NewFsPayModel(l.svcCtx.MysqlConn)
|
|
payList, err := payModel.GetListByOrderNumber(l.ctx, *orderInfo.Sn)
|
|
if err != nil {
|
|
logx.Error(err)
|
|
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get payment list")
|
|
}
|
|
for _, v := range payList {
|
|
tem := strings.ReplaceAll(constants.PAYMENT_HTML, "{{pay_amount}}", fmt.Sprintf("%.2f", float64(*v.PayAmount)/100))
|
|
tem = strings.ReplaceAll(tem, "{{brand}}", *v.Brand)
|
|
tem = strings.ReplaceAll(tem, "{{card_no}}", *v.CardNo)
|
|
payHtml.WriteString(tem)
|
|
}
|
|
detailCount := len(orderDetails)
|
|
|
|
for k, v := range orderDetails {
|
|
amount := float64(*v.Amount)
|
|
sumAmount := amount * float64(*v.BuyNum)
|
|
totalAmount += sumAmount
|
|
var style1, style2 string
|
|
if k == (detailCount - 1) {
|
|
style1 = "vertical-align: top;"
|
|
style2 = "padding-bottom: 20px; border-bottom: 1px solid #212121;"
|
|
}
|
|
tem := strings.ReplaceAll(constants.ORDER_HTML, "{{amount}}", fmt.Sprintf("%.2f", amount/100))
|
|
tem = strings.ReplaceAll(tem, "{{style1}}", style1)
|
|
tem = strings.ReplaceAll(tem, "{{style2}}", style2)
|
|
tem = strings.ReplaceAll(tem, "{{rowspan}}", rowspan)
|
|
tem = strings.ReplaceAll(tem, "{{buy_num}}", fmt.Sprintf("%d", *v.BuyNum))
|
|
tem = strings.ReplaceAll(tem, "{{sum_amount}}", fmt.Sprintf("%.2f", sumAmount/100))
|
|
if productIndex, ok := mapProduct[*v.ProductId]; ok {
|
|
tem = strings.ReplaceAll(tem, "{{product_title}}", *productList[productIndex].Title)
|
|
} else {
|
|
tem = strings.ReplaceAll(tem, "{{product_title}}", "")
|
|
}
|
|
orderHTML.WriteString(tem)
|
|
}
|
|
mainHtml := strings.ReplaceAll(constants.MAIN_INVOICE_HTML, "{{pay_html}}", payHtml.String())
|
|
mainHtml = strings.ReplaceAll(mainHtml, "{{amount_due}}", fmt.Sprintf("%.2f", float64(amountDue)/100))
|
|
mainHtml = strings.ReplaceAll(mainHtml, "{{second_payment_html}}", secondPaymentHtml)
|
|
mainHtml = strings.ReplaceAll(mainHtml, "{{total_amount}}", fmt.Sprintf("%.2f", totalAmount/100))
|
|
mainHtml = strings.ReplaceAll(mainHtml, "{{first_payment}}", fmt.Sprintf("%.2f", float64(firstPayment)/100))
|
|
mainHtml = strings.ReplaceAll(mainHtml, "{{orderHTML}}", orderHTML.String())
|
|
mainHtml = strings.ReplaceAll(mainHtml, "{{city}}", *address.City)
|
|
mainHtml = strings.ReplaceAll(mainHtml, "{{state}}", *address.State)
|
|
mainHtml = strings.ReplaceAll(mainHtml, "{{zip_code}}", *address.ZipCode)
|
|
mainHtml = strings.ReplaceAll(mainHtml, "{{street}}", *address.Street)
|
|
mainHtml = strings.ReplaceAll(mainHtml, "{{suite}}", *address.Suite)
|
|
mainHtml = strings.ReplaceAll(mainHtml, "{{name}}", userName)
|
|
mainHtml = strings.ReplaceAll(mainHtml, "{{first_style1}}", firstStyle1)
|
|
mainHtml = strings.ReplaceAll(mainHtml, "{{first_style2}}", firstStyle2)
|
|
mainHtml = strings.ReplaceAll(mainHtml, "{{h5Url}}", constants.H5_URL)
|
|
mainHtml = strings.ReplaceAll(mainHtml, "{{order_expire_time}}", time.Unix(*orderInfo.Ctime, req.TimeZone*60).Format("02 Jan,2006"))
|
|
//html内容页面转pdf的base64
|
|
prfBase64, err := pdf.HtmlToPdfBase64(mainHtml, 2)
|
|
if err != nil {
|
|
logx.Error(err)
|
|
return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to generate pdf file")
|
|
}
|
|
return resp.SetStatusWithMessage(basic.CodeOK, "success", types.GetOrderInvoiceRsp{
|
|
FileName: pdfFileName,
|
|
Pdf: prfBase64,
|
|
})
|
|
}
|