This commit is contained in:
桀尼龟 2025-06-12 16:38:55 +08:00
parent db54a355e8
commit 03574bd25f
8 changed files with 1444 additions and 751 deletions

File diff suppressed because it is too large Load Diff

View File

@ -17,6 +17,9 @@ var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
func (this *PackagePriceAndTimeResponse) Validate() error {
return nil
}
func (this *CommonResponse) Validate() error {
return nil
}
@ -108,6 +111,19 @@ func (this *OrderRecord) Validate() error {
}
return nil
}
func (this *OrderAddRecord) Validate() error {
for _, item := range this.AddPriceOptionsList {
if item != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("AddPriceOptionsList", err)
}
}
}
return nil
}
func (this *AddPriceOptionsInfo) Validate() error {
return nil
}
func (this *PriceOptionsInfo) Validate() error {
return nil
}

View File

@ -43,6 +43,8 @@ type BundleClient interface {
OrderRecordsList(ctx context.Context, in *OrderRecordsRequest, opts ...grpc_go.CallOption) (*OrderRecordsResponse, common.ErrorWithAttachment)
OrderRecordsDetail(ctx context.Context, in *OrderRecordsDetailRequest, opts ...grpc_go.CallOption) (*OrderRecordsDetailResponse, common.ErrorWithAttachment)
UpdateFinancialConfirmationStatus(ctx context.Context, in *FinancialConfirmationRequest, opts ...grpc_go.CallOption) (*CommonResponse, common.ErrorWithAttachment)
CreateOrderAddRecord(ctx context.Context, in *OrderAddRecord, opts ...grpc_go.CallOption) (*CommonResponse, common.ErrorWithAttachment)
PackagePriceAndTime(ctx context.Context, in *OrderRecord, opts ...grpc_go.CallOption) (*PackagePriceAndTimeResponse, common.ErrorWithAttachment)
//增值套餐
CreateValueAddBundle(ctx context.Context, in *CreateValueAddBundleRequest, opts ...grpc_go.CallOption) (*CreateValueAddBundleResponse, common.ErrorWithAttachment)
ValueAddBundleList(ctx context.Context, in *ValueAddBundleListRequest, opts ...grpc_go.CallOption) (*ValueAddBundleListResponse, common.ErrorWithAttachment)
@ -73,6 +75,8 @@ type BundleClientImpl struct {
OrderRecordsList func(ctx context.Context, in *OrderRecordsRequest) (*OrderRecordsResponse, error)
OrderRecordsDetail func(ctx context.Context, in *OrderRecordsDetailRequest) (*OrderRecordsDetailResponse, error)
UpdateFinancialConfirmationStatus func(ctx context.Context, in *FinancialConfirmationRequest) (*CommonResponse, error)
CreateOrderAddRecord func(ctx context.Context, in *OrderAddRecord) (*CommonResponse, error)
PackagePriceAndTime func(ctx context.Context, in *OrderRecord) (*PackagePriceAndTimeResponse, error)
CreateValueAddBundle func(ctx context.Context, in *CreateValueAddBundleRequest) (*CreateValueAddBundleResponse, error)
ValueAddBundleList func(ctx context.Context, in *ValueAddBundleListRequest) (*ValueAddBundleListResponse, error)
ValueAddBundleDetail func(ctx context.Context, in *ValueAddBundleDetailRequest) (*ValueAddBundleDetailResponse, error)
@ -183,6 +187,18 @@ func (c *bundleClient) UpdateFinancialConfirmationStatus(ctx context.Context, in
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/UpdateFinancialConfirmationStatus", in, out)
}
func (c *bundleClient) CreateOrderAddRecord(ctx context.Context, in *OrderAddRecord, opts ...grpc_go.CallOption) (*CommonResponse, common.ErrorWithAttachment) {
out := new(CommonResponse)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/CreateOrderAddRecord", in, out)
}
func (c *bundleClient) PackagePriceAndTime(ctx context.Context, in *OrderRecord, opts ...grpc_go.CallOption) (*PackagePriceAndTimeResponse, common.ErrorWithAttachment) {
out := new(PackagePriceAndTimeResponse)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/PackagePriceAndTime", in, out)
}
func (c *bundleClient) CreateValueAddBundle(ctx context.Context, in *CreateValueAddBundleRequest, opts ...grpc_go.CallOption) (*CreateValueAddBundleResponse, common.ErrorWithAttachment) {
out := new(CreateValueAddBundleResponse)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
@ -238,6 +254,8 @@ type BundleServer interface {
OrderRecordsList(context.Context, *OrderRecordsRequest) (*OrderRecordsResponse, error)
OrderRecordsDetail(context.Context, *OrderRecordsDetailRequest) (*OrderRecordsDetailResponse, error)
UpdateFinancialConfirmationStatus(context.Context, *FinancialConfirmationRequest) (*CommonResponse, error)
CreateOrderAddRecord(context.Context, *OrderAddRecord) (*CommonResponse, error)
PackagePriceAndTime(context.Context, *OrderRecord) (*PackagePriceAndTimeResponse, error)
//增值套餐
CreateValueAddBundle(context.Context, *CreateValueAddBundleRequest) (*CreateValueAddBundleResponse, error)
ValueAddBundleList(context.Context, *ValueAddBundleListRequest) (*ValueAddBundleListResponse, error)
@ -299,6 +317,12 @@ func (UnimplementedBundleServer) OrderRecordsDetail(context.Context, *OrderRecor
func (UnimplementedBundleServer) UpdateFinancialConfirmationStatus(context.Context, *FinancialConfirmationRequest) (*CommonResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateFinancialConfirmationStatus not implemented")
}
func (UnimplementedBundleServer) CreateOrderAddRecord(context.Context, *OrderAddRecord) (*CommonResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreateOrderAddRecord not implemented")
}
func (UnimplementedBundleServer) PackagePriceAndTime(context.Context, *OrderRecord) (*PackagePriceAndTimeResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method PackagePriceAndTime not implemented")
}
func (UnimplementedBundleServer) CreateValueAddBundle(context.Context, *CreateValueAddBundleRequest) (*CreateValueAddBundleResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreateValueAddBundle not implemented")
}
@ -780,6 +804,64 @@ func _Bundle_UpdateFinancialConfirmationStatus_Handler(srv interface{}, ctx cont
return interceptor(ctx, in, info, handler)
}
func _Bundle_CreateOrderAddRecord_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(OrderAddRecord)
if err := dec(in); err != nil {
return nil, err
}
base := srv.(dubbo3.Dubbo3GrpcService)
args := []interface{}{}
args = append(args, in)
md, _ := metadata.FromIncomingContext(ctx)
invAttachment := make(map[string]interface{}, len(md))
for k, v := range md {
invAttachment[k] = v
}
invo := invocation.NewRPCInvocation("CreateOrderAddRecord", args, invAttachment)
if interceptor == nil {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
info := &grpc_go.UnaryServerInfo{
Server: srv,
FullMethod: ctx.Value("XXX_TRIPLE_GO_INTERFACE_NAME").(string),
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
return interceptor(ctx, in, info, handler)
}
func _Bundle_PackagePriceAndTime_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(OrderRecord)
if err := dec(in); err != nil {
return nil, err
}
base := srv.(dubbo3.Dubbo3GrpcService)
args := []interface{}{}
args = append(args, in)
md, _ := metadata.FromIncomingContext(ctx)
invAttachment := make(map[string]interface{}, len(md))
for k, v := range md {
invAttachment[k] = v
}
invo := invocation.NewRPCInvocation("PackagePriceAndTime", args, invAttachment)
if interceptor == nil {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
info := &grpc_go.UnaryServerInfo{
Server: srv,
FullMethod: ctx.Value("XXX_TRIPLE_GO_INTERFACE_NAME").(string),
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
return interceptor(ctx, in, info, handler)
}
func _Bundle_CreateValueAddBundle_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(CreateValueAddBundleRequest)
if err := dec(in); err != nil {
@ -1021,6 +1103,14 @@ var Bundle_ServiceDesc = grpc_go.ServiceDesc{
MethodName: "UpdateFinancialConfirmationStatus",
Handler: _Bundle_UpdateFinancialConfirmationStatus_Handler,
},
{
MethodName: "CreateOrderAddRecord",
Handler: _Bundle_CreateOrderAddRecord_Handler,
},
{
MethodName: "PackagePriceAndTime",
Handler: _Bundle_PackagePriceAndTime_Handler,
},
{
MethodName: "CreateValueAddBundle",
Handler: _Bundle_CreateValueAddBundle_Handler,

View File

@ -150,6 +150,7 @@ func CheckWebLogin(provider *account.AccountClientImpl) gin.HandlerFunc {
loginInfo := login.Info{
Domain: info.Domain,
ID: info.ID,
Name: info.NickName,
//Account: info.Account,
//NickName: info.NickName,
//PositionUsers: qres.PositionUsers,

View File

@ -38,6 +38,7 @@ func BundleOrderRouter(r *gin.RouterGroup) {
bundleOrderAppRoute := bundleOrderRoute.Group("app")
{
bundleOrderAppRoute.POST("order-signature", bundle.CreateBundleOrderSignature)
bundleOrderAppRoute.POST("order-add-signature", bundle.CreateBundleOrderAddSignature)
bundleOrderAppRoute.POST("update-pay", bundle.UpdateBundleOrderStatusPaid)
bundleOrderAppRoute.POST("order-detail", bundle.OrderRecordsDetail)

View File

@ -14,11 +14,178 @@ import (
bundleModel "fonchain-fiee/pkg/service/bundle/model"
"strconv"
"strings"
"time"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
)
func CreateBundleOrderAddSignature(c *gin.Context) {
var req bundle.OrderAddRecord
if err := c.ShouldBindBodyWith(&req, binding.JSON); err != nil {
service.Error(c, err)
return
}
if req.Language == "" {
service.Error(c, errors.New(common.MissLanguageTypes))
return
}
if req.BundleUuid == "" {
service.Error(c, errors.New(common.MissOrderNo))
return
}
// 获取用户信息
userInfo := login.GetUserInfoFromC(c)
if msg, exists := map[int32]string{
1: common.Unnamed,
2: common.UnderReview,
3: common.ReviewFailed,
}[userInfo.Status]; userInfo.Status != 4 {
if exists {
service.Error(c, errors.New(msg))
} else {
service.Error(c, errors.New(common.UnknownStatus))
}
return
}
// 校验套餐是否已购买
orderRecordReq := bundle.OrderRecordsDetailRequest{
Uuid: req.BundleUuid,
CustomerID: strconv.FormatUint(userInfo.ID, 10),
}
orderRecordResp, err := service.BundleProvider.OrderRecordsDetail(context.Background(), &orderRecordReq)
if err != nil {
service.Error(c, err)
return
}
if orderRecordResp.OrderRecord.ExpirationTime == "" || orderRecordResp.OrderRecord.ExpirationTime > time.Now().Format("2006-01-02") {
service.Error(c, errors.New(common.ThePackageHasExpired))
return
}
// 获取套餐详情(待替换逻辑)
bundleDetail, err := service.BundleProvider.BundleDetail(context.Background(), &bundle.BundleDetailRequest{
Uuid: req.BundleUuid,
})
if err != nil {
service.Error(c, err)
return
}
// todo 需要判断购买的增值服务是否为可用时长 如果为可以用时长 合同截止日期为购买时长时间 否则合同截止日期为主套餐截止日期
// 处理多个增值服务
type ValueAddServiceInfo struct {
Service *bundle.ValueAddServiceLang
Options *bundle.ValueAddPriceOptions
ID int32
}
var (
valueAddServices []ValueAddServiceInfo
totalAmount float64
mainDeadline = orderRecordResp.OrderRecord.ExpirationTime
)
for _, opt := range req.AddPriceOptionsList {
valueAddInfo, err := service.BundleProvider.ValueAddServiceDetail(context.Background(), &bundle.ValueAddServiceDetailRequest{
Uuid: opt.ValueUid,
Language: req.Language,
})
if err != nil {
service.Error(c, err)
return
}
// 找到匹配的选项
var selectedOption *bundle.ValueAddPriceOptions
for _, option := range valueAddInfo.ValueAddServiceLang.Options {
if int32(option.Id) == opt.Id {
selectedOption = option
break
}
}
if selectedOption == nil {
service.Error(c, errors.New("未找到匹配的价格选项"))
return
}
valueAddServices = append(valueAddServices, ValueAddServiceInfo{
Service: valueAddInfo.ValueAddServiceLang,
Options: selectedOption,
ID: opt.Id,
})
}
// 计算总金额和确定截止日期
var expirationDate string
for _, svc := range valueAddServices {
price, err := strconv.ParseFloat(svc.Options.Price, 64)
if err != nil {
service.Error(c, errors.New("价格格式错误"))
return
}
var nowAmount float64
switch svc.Service.PriceMode {
case 1: // 数量×单价模式
nowAmount = float64(svc.Options.Num) * price
totalAmount += float64(svc.Options.Num) * price
case 2: // 固定价格模式
nowAmount = price
totalAmount += price
}
req.AddPriceOptionsList = append(req.AddPriceOptionsList, &bundle.AddPriceOptionsInfo{
ValueUid: svc.Service.Uuid,
ServiceType: svc.Service.ServiceType,
CurrencyType: svc.Service.PriceType,
Amount: float32(nowAmount),
Num: svc.Options.Num,
Unit: svc.Service.Unit,
})
// 如果是可用时长服务,计算新的截止日期
if svc.Service.ServiceType == 5 {
newDeadline := calculateExpirationDate(svc.Options.Num, svc.Service.Unit)
if expirationDate == "" || newDeadline > expirationDate {
expirationDate = newDeadline
}
}
}
// 如果没有可用时长服务,使用主套餐截止日期
if expirationDate == "" {
expirationDate = mainDeadline
}
req.CustomerNum = userInfo.SubNum
req.CustomerName = userInfo.Name
req.CustomerID = strconv.FormatUint(userInfo.ID, 10)
req.Source = 2
req.SignedTime = common.GetBeijingTime()
req.ExpirationDate = expirationDate
// 当前 未将 签名 写入合同中
signContract, signContractErr := logic.SignContractV2(req.CustomerNum, bundleDetail.Bundle.Contract, float32(totalAmount), expirationDate)
if signContractErr != nil {
service.Error(c, signContractErr)
return
}
req.SignContract = signContract
// 创建增值服务订单记录
res, err := service.BundleProvider.CreateOrderAddRecord(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
service.Success(c, res)
}
// 计算截止日期辅助函数
func calculateExpirationDate(num int32, unit string) string {
now := time.Now()
switch unit {
case "天":
return now.AddDate(0, 0, int(num)).Format("2006-01-02")
case "月":
return now.AddDate(0, int(num), 0).Format("2006-01-02")
case "年":
return now.AddDate(int(num), 0, 0).Format("2006-01-02")
default:
return ""
}
}
func CreateBundleOrderSignature(c *gin.Context) {
var req bundle.OrderRecord
@ -40,10 +207,22 @@ func CreateBundleOrderSignature(c *gin.Context) {
service.Error(c, errors.New(common.MissOrderSignature))
return
}*/
statusMessages := map[int32]string{
1: common.Unnamed,
2: common.UnderReview,
3: common.ReviewFailed,
}
// 获取 用户信息
userInfo := login.GetUserInfoFromC(c)
if userInfo.Status != 4 {
if msg, exists := statusMessages[userInfo.Status]; exists {
service.Error(c, errors.New(msg))
return
} else {
service.Error(c, errors.New(common.UnknownStatus))
return
}
}
// 校验 当前用户只能买一次套餐
orderRecordsListReq := bundle.OrderRecordsRequest{
CustomerID: strconv.FormatUint(userInfo.ID, 10),
@ -53,10 +232,10 @@ func CreateBundleOrderSignature(c *gin.Context) {
service.Error(c, orderRecordsListErr)
return
}
//有套餐并且套餐未过期
if orderRecordsList.OrderRecords != nil {
for _, order := range orderRecordsList.OrderRecords {
if order.CustomerID == strconv.FormatUint(userInfo.ID, 10) {
for _, orderInfo := range orderRecordsList.OrderRecords {
if orderInfo.CustomerID == strconv.FormatUint(userInfo.ID, 10) && orderInfo.ExpirationTime > time.Now().Format("2006-01-02") {
service.Error(c, errors.New(common.HadOrder))
return
}
@ -127,13 +306,20 @@ func CreateBundleOrderSignature(c *gin.Context) {
req.Amount = bundleDetail.Bundle.Price
req.AmountType = bundleDetail.Bundle.PriceType
req.BundleCommonUid = bundleDetail.Bundle.BundleCommonUid
req.TotalAmount = req.Amount + req.ValueAddBundleAmount
req.TotalAmount = bundleDetail.Bundle.Price
req.PayType = 1 // 默认 人民币
//获取过期时间和增值服务金额
PriceAndTime, err := service.BundleProvider.PackagePriceAndTime(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
//套餐金额+增值服务金额
totalAmount := PriceAndTime.Price + bundleDetail.Bundle.Price
req.ContractNo = common.GenerateContractNo(lastContractNo)
// 当前 未将 签名 写入合同中
signContract, signContractErr := logic.SignContractV2(req.CustomerNum, bundleDetail.Bundle.Contract, req.TotalAmount, bundleDetail.Bundle.ContractDuration)
// 当前 未将 签名 写入合同中 todo 金额和有效时间待修改
signContract, signContractErr := logic.SignContractV2(req.CustomerNum, bundleDetail.Bundle.Contract, totalAmount, PriceAndTime.Time)
if signContractErr != nil {
service.Error(c, signContractErr)
return

View File

@ -20,6 +20,7 @@ const (
HadOrder = "您已购买过套餐,无法再次购买"
InvalidValueAddBundleNum = "套餐数量无效"
ThePackageHasExpired = "当前套餐已过期"
)
const (
@ -35,6 +36,12 @@ const (
ErrorDownloadFile = "下载文件失败"
ErrorUploadFile = "上传文件失败"
)
const (
Unnamed = "请先实名"
UnderReview = "实名审核中"
ReviewFailed = "实名审核失败"
UnknownStatus = "未知实名状态"
)
/*var EnMessages = map[string]string{
"创建套餐信息失败": "Failed to create bundle information",

View File

@ -14,7 +14,7 @@ import (
"time"
)
func SignContractV2(customerNum, contract string, price float32, contractDuration int64) (outputUrl string, err error) {
func SignContractV2(customerNum, contract string, price float32, expirationDate string) (outputUrl string, err error) {
filePath := model.MediaPath + customerNum + time.Now().Format("20060102150405") + ".pdf"
downloadFileErr := DownloadFile(filePath, contract)
if downloadFileErr != nil {
@ -31,7 +31,7 @@ func SignContractV2(customerNum, contract string, price float32, contractDuratio
return outputUrl, errors.New(common.ErrorInsertSignature)
}*/
signErr := InsertSignatureV2(filePath, signFile, price, contractDuration)
signErr := InsertSignatureV2(filePath, signFile, price, expirationDate)
if signErr != nil {
zap.L().Error("insert signature error: ", zap.Error(signErr))
return outputUrl, errors.New(common.ErrorInsertSignature)
@ -46,7 +46,7 @@ func SignContractV2(customerNum, contract string, price float32, contractDuratio
return outputUrl, nil
}
func InsertSignatureV2(templatePath, outputPath string, price float32, contractDuration int64) error {
func InsertSignatureV2(templatePath, outputPath string, price float32, expirationDate string) error {
pdf := gopdf.GoPdf{}
pdf.Start(gopdf.Config{PageSize: *gopdf.PageSizeA4})
@ -90,22 +90,28 @@ func InsertSignatureV2(templatePath, outputPath string, price float32, contractD
pdf.SetPage(limitTimePage)
// 英文格式的时间
t := time.Now().AddDate(int(contractDuration), 0, 0)
parsedTime, err := time.Parse("2006-01-02", expirationDate)
if err != nil {
panic("日期格式错误!")
}
year := parsedTime.Format("2006") // "2006"
month := parsedTime.Format("01") // "01"
day := parsedTime.Format("02") // "02"
pdf.SetX(160)
pdf.SetY(387)
pdf.Cell(nil, t.Format("2006-01-02"))
pdf.Cell(nil, expirationDate)
pdf.SetX(330)
pdf.SetY(403)
pdf.Cell(nil, t.Format("2006"))
pdf.Cell(nil, year)
pdf.SetX(396)
pdf.SetY(403)
pdf.Cell(nil, t.Format("01"))
pdf.Cell(nil, month)
pdf.SetX(443)
pdf.SetY(403)
pdf.Cell(nil, t.Format("02"))
pdf.Cell(nil, day)
// 生成新的 PDF
if err = pdf.WritePdf(outputPath); err != nil {