package svc import ( "applet/app/enum" "applet/app/md" "applet/app/utils" db "code.fnuoos.com/zhimeng/model.git/src" "code.fnuoos.com/zhimeng/model.git/src/super/implement" "code.fnuoos.com/zhimeng/model.git/src/super/model" "errors" "time" ) func GenerateWxAdData(req md.GenerateWxAdData) (err error, generateWxAdData model.GenerateWxAdData) { //1、查找原始数据记录 originalWxAdDataDb := implement.NewOriginalWxAdDataDb(db.Db) originalWxAdData, err := originalWxAdDataDb.GetOriginalWxAdData(req.OriginalDataId) if err != nil { return } if originalWxAdData == nil { err = errors.New("未查询到原始数据记录") return } //2、查询对应媒体、代理的分成策略 mediumDivisionStrategyDb := implement.NewMediumDivisionStrategyDb(db.Db) mediumDivisionStrategy, err := mediumDivisionStrategyDb.GetOriginalWxAdDataByMediumId(originalWxAdData.MediumId) if err != nil { return } if mediumDivisionStrategy == nil { err = errors.New("未查询到对应代理的分成策略") return } mediumDivisionStrategyWithAgentFlowDb := implement.NewMediumDivisionStrategyWithAgentFlowDb(db.Db) mediumDivisionStrategyWithAgentFlows, err := mediumDivisionStrategyWithAgentFlowDb.FindMediumDivisionStrategyWithAgentFlowByStrategyId(mediumDivisionStrategy.MediumId) if err != nil { return } //3、计算媒体、代理收益、平台留存、佣金留存、协议分成、协议总分成 publisherIncome := originalWxAdData.PublisherIncome mediaRevenue := publisherIncome * mediumDivisionStrategy.MediaRevenueRate / 100 //媒体收益 agentRevenue := publisherIncome * mediumDivisionStrategy.AgentRevenueRate / 100 //代理收益 platformRetention := publisherIncome * mediumDivisionStrategy.PlatformRetentionRate / 100 //平台留存 commissionRetention := publisherIncome * mediumDivisionStrategy.CommissionRetentionRate / 100 //佣金留存 agreementSharingTotal := (mediaRevenue + agentRevenue) / (100 - mediumDivisionStrategy.AgreementSharingRate) //协议总分成(倒推) agreementSharing := agreementSharingTotal - (mediaRevenue + agentRevenue) //协议分成 //3、判断是否有调价留存 var priceAdjustmentRetention int if req.NowEcpm != req.OriginalEcpm || req.NowExposureCount != req.OriginalExposureCount { tmpMediaRevenue := int(utils.StrToFloat64(req.NowEcpm) * float64(req.NowExposureCount) / 1000) priceAdjustmentRetention = tmpMediaRevenue - mediaRevenue mediaRevenue = tmpMediaRevenue } //4、计算各代理收益 var extraRevenue int var agentRevenueFlows []struct { AgentId int `json:"agent_id"` AgentRevenueRate int `json:"agent_revenue_rate"` ExtraRevenueRate int `json:"extra_revenue_rate"` AgentRevenue int `json:"agent_revenue"` ExtraRevenue int `json:"extra_revenue"` } for _, v := range *mediumDivisionStrategyWithAgentFlows { tmpAgentRevenue := agentRevenue * v.AgentRevenueRate / 100 tmpExtraRevenue := commissionRetention * v.ExtraRevenueRate / 100 extraRevenue += tmpExtraRevenue agentRevenueFlows = append(agentRevenueFlows, struct { AgentId int `json:"agent_id"` AgentRevenueRate int `json:"agent_revenue_rate"` ExtraRevenueRate int `json:"extra_revenue_rate"` AgentRevenue int `json:"agent_revenue"` ExtraRevenue int `json:"extra_revenue"` }{ AgentId: v.AgentId, AgentRevenueRate: v.AgentRevenueRate, ExtraRevenueRate: v.ExtraRevenueRate, AgentRevenue: tmpAgentRevenue, ExtraRevenue: tmpExtraRevenue, }) } //5、插入 generate_wx_ad_data 、generate_wx_ad_data_with_agent_flow 数据 session := db.Db.NewSession() defer session.Close() session.Begin() now := time.Now() generateWxAdData = model.GenerateWxAdData{ MediumId: originalWxAdData.MediumId, Uuid: originalWxAdData.Uuid, AppId: originalWxAdData.AppId, PlatformAppId: originalWxAdData.PlatformAppId, OriginalDataId: originalWxAdData.Id, SlotId: originalWxAdData.SlotId, AdSlot: originalWxAdData.AdSlot, Date: originalWxAdData.Date, ReqSuccCount: originalWxAdData.ReqSuccCount, ExposureCount: req.NowExposureCount, //现-曝光量 ExposureRate: originalWxAdData.ExposureRate, ClickCount: originalWxAdData.ClickCount, ClickRate: originalWxAdData.ClickRate, Ecpm: req.NowEcpm, //现-ecpm PlatformRetention: platformRetention, CommissionRetention: commissionRetention, PriceAdjustmentRetention: priceAdjustmentRetention, MediaRevenue: mediaRevenue, AgentRevenue: agentRevenue, ExtraRevenue: extraRevenue, AgreementSharing: agreementSharing, AgreementSharingTotal: agreementSharingTotal, PlatformRetentionRate: mediumDivisionStrategy.PlatformRetentionRate, CommissionRetentionRate: mediumDivisionStrategy.CommissionRetentionRate, MediaRevenueRate: mediumDivisionStrategy.MediaRevenueRate, AgentRevenueRate: mediumDivisionStrategy.AgentRevenueRate, ExtraRevenueRate: mediumDivisionStrategy.ExtraRevenueRate, AgreementSharingRate: mediumDivisionStrategy.AgreementSharingRate, IsGenerateReport: 0, CreateAt: now.Format("2006-01-02 15:04:05"), UpdateAt: now.Format("2006-01-02 15:04:05"), Platform: originalWxAdData.Platform, } generateWxAdDataDb := implement.NewGenerateWxAdDataDb(db.Db) _, err = generateWxAdDataDb.GenerateWxAdDataInsertBySession(session, &generateWxAdData) if err != nil { _ = session.Rollback() return } var generateWxAdDataWithAgentFlows []*model.GenerateWxAdDataWithAgentFlow for _, v := range agentRevenueFlows { generateWxAdDataWithAgentFlows = append(generateWxAdDataWithAgentFlows, &model.GenerateWxAdDataWithAgentFlow{ Uuid: generateWxAdData.Uuid, AppId: generateWxAdData.AppId, PlatformAppId: generateWxAdData.PlatformAppId, AgentId: v.AgentId, GenerateDataId: generateWxAdData.Id, SlotId: generateWxAdData.SlotId, AdSlot: generateWxAdData.AdSlot, Date: generateWxAdData.Date, AgentRevenue: v.AgentRevenue, AgentRevenueRate: v.AgentRevenueRate, ExtraRevenue: v.ExtraRevenue, ExtraRevenueRate: v.ExtraRevenueRate, CreateAt: now.Format("2006-01-02 15:04:05"), UpdateAt: now.Format("2006-01-02 15:04:05"), }) } generateWxAdDataWithAgentFlowDb := implement.NewGenerateWxAdDataWithAgentFlowDb(db.Db) _, err = generateWxAdDataWithAgentFlowDb.BatchAddGenerateWxAdDataWithAgentFlow(session, generateWxAdDataWithAgentFlows) if err != nil { _ = session.Rollback() return } //6、修改 original_wx_ad_data 记录中的 is_apply(是否已应用(0:未 1:已) ) originalWxAdData.IsApply = 1 _, err = originalWxAdDataDb.UpdateOriginalWxAdDataBySession(session, originalWxAdData, "is_apply") if err != nil { _ = session.Rollback() return } return session.Commit(), generateWxAdData } func ClacEcpm(req md.ClacEcpmReq) (err error, ecpm string) { //1、查找原始数据记录 originalWxAdDataDb := implement.NewOriginalWxAdDataDb(db.Db) originalWxAdData, err := originalWxAdDataDb.GetOriginalWxAdData(req.GenerateDataId) if err != nil { return } if originalWxAdData == nil { err = errors.New("未查询到原始数据记录") return } //2、查询对应媒体分成策略 mediumDivisionStrategyDb := implement.NewMediumDivisionStrategyDb(db.Db) mediumDivisionStrategy, err := mediumDivisionStrategyDb.GetOriginalWxAdDataByMediumId(originalWxAdData.MediumId) if err != nil { return } if mediumDivisionStrategy == nil { err = errors.New("未查询到对应代理的分成策略") return } //3、计算媒体、代理收益、协议总分成 publisherIncome := originalWxAdData.PublisherIncome mediaRevenue := publisherIncome * mediumDivisionStrategy.MediaRevenueRate / 100 //媒体收益 agentRevenue := publisherIncome * mediumDivisionStrategy.AgentRevenueRate / 100 //代理收益 agreementSharingTotal := (mediaRevenue + agentRevenue) / (100 - mediumDivisionStrategy.AgreementSharingRate) //协议总分成(倒推) //4、倒退出当前ecpm值 ecpm = utils.Float64ToStrPrec4(float64(agreementSharingTotal) / (float64(originalWxAdData.ExposureCount) / 1000)) return } func SettlementWxAdData(req md.SettlementWxAdData) (err error) { //1、查找生成数据记录 generateWxAdDataDb := implement.NewGenerateWxAdDataDb(db.Db) generateWxAdData, err := generateWxAdDataDb.GetGenerateWxAdData(req.GenerateDataId) if err != nil { return } if generateWxAdData == nil { err = errors.New("未查询到生成数据记录") return } originalWxAdDataDb := implement.NewOriginalWxAdDataDb(db.Db) originalWxAdData, err := originalWxAdDataDb.GetOriginalWxAdData(generateWxAdData.OriginalDataId) if err != nil { return } if originalWxAdData == nil { err = errors.New("未查询到原始数据记录") return } //2、查询 生成数据-代理明细 记录 generateWxAdDataWithAgentFlowDb := implement.NewGenerateWxAdDataWithAgentFlowDb(db.Db) generateWxAdDataWithAgentFlow, err := generateWxAdDataWithAgentFlowDb.FindGenerateWxAdDataWithAgentFlowByStrategyId(generateWxAdData.Id) if err != nil { return } //3、查询 媒体、代理的结算方式 mediumListDb := implement.NewMediumListDb(db.Db) medium, err := mediumListDb.GetMediumList(originalWxAdData.MediumId) if err != nil { return } if medium == nil { return errors.New("媒体:" + utils.IntToStr(originalWxAdData.MediumId) + "未查询到对应记录") } var agentMap = map[int]model.AgentList{} agentListDb := implement.NewAgentListDb(db.Db) for _, v := range *generateWxAdDataWithAgentFlow { agent, err1 := agentListDb.GetAgentList(v.AgentId) if err1 != nil { return err1 } if agent == nil { return errors.New("代理:" + utils.IntToStr(v.AgentId) + "未查询到对应记录") } agentMap[v.AgentId] = *agent } //4、生成数据 now := time.Now() session := db.Db.NewSession() defer session.Close() session.Begin() //4.1 新增/更新 medium_settlement 数据 mediumSettlementDb := implement.NewMediumSettlementDb(db.Db) mediumSettlement, err := mediumSettlementDb.GetMediumSettlementForAvailable(originalWxAdData.MediumId) if err != nil { return } var basicIncomeBefore, mediumSettlementState, mediumSettlementPayState int //判断是否为预付结算类型 if medium.SettlementType == enum.MediumSettlementTypeForPaymentInAdvance { mediumSettlementState = enum.MediumSettlementStateForCompleteSign mediumSettlementPayState = enum.MediumSettlementPayStateForPaymentAlready } if mediumSettlement == nil { //新增一条数据 mediumSettlement = &model.MediumSettlement{ Uuid: originalWxAdData.Uuid, MediumId: originalWxAdData.MediumId, AppId: originalWxAdData.AppId, PlatformAppId: originalWxAdData.PlatformAppId, BusinessKind: 1, Kind: medium.SettlementType, BasicIncome: generateWxAdData.MediaRevenue, OtherIncome: 0, OriginalIncome: originalWxAdData.PublisherIncome, PlatformRetention: generateWxAdData.PlatformRetention, CommissionRetention: generateWxAdData.CommissionRetention, PriceAdjustmentRetention: generateWxAdData.PriceAdjustmentRetention, State: mediumSettlementState, PayState: mediumSettlementPayState, StartDate: now.Format("2006-01-02"), EndDate: "", CreateAt: now.Format("2006-01-02 15:04:05"), UpdateAt: now.Format("2006-01-02 15:04:05"), SettleFile: "", } _, err = mediumSettlementDb.MediumSettlementInsertBySession(session, mediumSettlement) if err != nil { _ = session.Rollback() return } } else { //更新数据 if medium.SettlementType != mediumSettlement.Kind { //TODO::前后结算类型不一致,之前结算单状态自动变成"核算中" mediumSettlement.State = enum.MediumSettlementStateForAccountingInProgress //mediumSettlement.PayState = mediumSettlementPayState _, err = mediumSettlementDb.UpdateMediumSettlementBySession(session, mediumSettlement, "state") if err != nil { _ = session.Rollback() return } //新增一条数据 mediumSettlement = &model.MediumSettlement{ Uuid: originalWxAdData.Uuid, MediumId: originalWxAdData.MediumId, AppId: originalWxAdData.AppId, PlatformAppId: originalWxAdData.PlatformAppId, BusinessKind: 1, Kind: medium.SettlementType, BasicIncome: generateWxAdData.MediaRevenue, OtherIncome: 0, OriginalIncome: originalWxAdData.PublisherIncome, PlatformRetention: generateWxAdData.PlatformRetention, CommissionRetention: generateWxAdData.CommissionRetention, PriceAdjustmentRetention: generateWxAdData.PriceAdjustmentRetention, State: mediumSettlementState, PayState: mediumSettlementPayState, StartDate: now.Format("2006-01-02"), EndDate: "", CreateAt: now.Format("2006-01-02 15:04:05"), UpdateAt: now.Format("2006-01-02 15:04:05"), SettleFile: "", } _, err = mediumSettlementDb.MediumSettlementInsertBySession(session, mediumSettlement) if err != nil { _ = session.Rollback() return } } else { basicIncomeBefore = mediumSettlement.BasicIncome mediumSettlement.BasicIncome += generateWxAdData.MediaRevenue mediumSettlement.OriginalIncome += originalWxAdData.PublisherIncome mediumSettlement.PlatformRetention += generateWxAdData.PlatformRetention mediumSettlement.CommissionRetention += generateWxAdData.CommissionRetention mediumSettlement.PriceAdjustmentRetention += generateWxAdData.PriceAdjustmentRetention _, err = mediumSettlementDb.UpdateMediumSettlementBySession(session, mediumSettlement, "basic_income", "original_income", "platform_retention", "commission_retention", "price_adjustment_retention") if err != nil { _ = session.Rollback() return } } } if medium.SettlementType == enum.MediumSettlementTypeForPaymentInAdvance { err = DealMediumAmount(session, md.DealMediumAmount{ Mid: utils.IntToStr(originalWxAdData.Uuid), Type: md.FinMediumFlowDirectionExpenditure, Kind: md.SettlementSubKindForMediumFlow, OrdId: utils.IntToStr(mediumSettlement.Id), MediumId: originalWxAdData.MediumId, Amount: float64(generateWxAdData.MediaRevenue) / 100, Memo: md.SettlementSubTitleForMediumFlow, }) if err != nil { _ = session.Rollback() return } } //4.2 新增 medium_settlement_with_flow 数据 mediumSettlementWithFlowDb := implement.NewMediumSettlementWithFlowDb(db.Db) _, err = mediumSettlementWithFlowDb.MediumSettlementWithFlowInsertBySession(session, &model.MediumSettlementWithFlow{ SettlementId: mediumSettlement.Id, GenerateDataId: generateWxAdData.Id, Amount: generateWxAdData.MediaRevenue, BasicIncomeBefore: basicIncomeBefore, BasicIncomeAfter: mediumSettlement.BasicIncome, OtherIncomeBefore: 0, OtherIncomeAfter: 0, Kind: enum.MediumSettlementWithFlowKindForBasicIncome, CreateAt: now.Format("2006-01-02 15:04:05"), UpdateAt: now.Format("2006-01-02 15:04:05"), }) if err != nil { _ = session.Rollback() return } //4.3 新增 agent_settlement、agent_settlement_with_flow 数据 agentSettlementDb := implement.NewAgentSettlementDb(db.Db) agentSettlementWithFlowDb := implement.NewAgentSettlementWithFlowDb(db.Db) for _, v := range *generateWxAdDataWithAgentFlow { agentSettlement, err1 := agentSettlementDb.GetAgentSettlementForAvailable(v.AgentId) if err1 != nil { _ = session.Rollback() return err1 } var agentBasicIncomeBefore, agentOtherIncomeBefore, agentSettlementState, agentSettlementPayState int //判断是否为预付结算类型 if agentMap[v.AgentId].SettlementType == enum.AgentSettlementTypeForPaymentInAdvance { agentSettlementState = enum.AgentSettlementStateForCompleteSign agentSettlementPayState = enum.AgentSettlementPayStateForPaymentAlready } if agentSettlement == nil { //新增一条数据 agentSettlement = &model.AgentSettlement{ Uuid: v.Uuid, AgentId: v.AgentId, MediumId: originalWxAdData.MediumId, AppId: v.AppId, PlatformAppId: v.PlatformAppId, BusinessKind: 1, Kind: agentMap[v.AgentId].SettlementType, BasicIncome: v.AgentRevenue, OtherIncome: v.ExtraRevenue, State: agentSettlementState, PayState: agentSettlementPayState, StartDate: now.Format("2006-01-02"), EndDate: "", CreateAt: now.Format("2006-01-02 15:04:05"), UpdateAt: now.Format("2006-01-02 15:04:05"), } _, err = agentSettlementDb.AgentSettlementInsertBySession(session, agentSettlement) if err != nil { _ = session.Rollback() return } } else { //更新数据 if agentMap[v.AgentId].SettlementType != agentSettlement.Kind { //TODO::前后结算类型不一致,之前结算单状态自动变成"核算中" agentSettlement.State = enum.AgentSettlementStateForAccountingInProgress _, err = agentSettlementDb.UpdateAgentSettlementBySession(session, agentSettlement, "state") if err != nil { _ = session.Rollback() return } //新增一条数据 agentSettlement = &model.AgentSettlement{ Uuid: v.Uuid, AgentId: v.AgentId, MediumId: originalWxAdData.MediumId, AppId: v.AppId, PlatformAppId: v.PlatformAppId, BusinessKind: 1, Kind: agentMap[v.AgentId].SettlementType, BasicIncome: v.AgentRevenue, OtherIncome: v.ExtraRevenue, State: agentSettlementState, PayState: agentSettlementPayState, StartDate: now.Format("2006-01-02"), EndDate: "", CreateAt: now.Format("2006-01-02 15:04:05"), UpdateAt: now.Format("2006-01-02 15:04:05"), } _, err = agentSettlementDb.AgentSettlementInsertBySession(session, agentSettlement) if err != nil { _ = session.Rollback() return } } else { agentBasicIncomeBefore = agentSettlement.BasicIncome agentOtherIncomeBefore = agentSettlement.OtherIncome agentSettlement.BasicIncome += v.AgentRevenue agentSettlement.OtherIncome += v.ExtraRevenue _, err = agentSettlementDb.UpdateAgentSettlementBySession(session, agentSettlement, "basic_income", "other_income") if err != nil { _ = session.Rollback() return } } } if agentMap[v.AgentId].SettlementType == enum.AgentSettlementTypeForPaymentInAdvance { err = DealAgentAmount(session, md.DealAgentAmount{ Mid: utils.IntToStr(originalWxAdData.Uuid), Type: md.FinAgentFlowDirectionExpenditure, Kind: md.SettlementSubKindForAgentFlow, OrdId: utils.IntToStr(v.Id), Amount: float64(v.AgentRevenue)/100 + float64(v.ExtraRevenue)/100, Memo: md.SettlementSubTitleForMediumFlow, }) if err != nil { _ = session.Rollback() return } } _, err = agentSettlementWithFlowDb.AgentSettlementWithFlowInsertBySession(session, &model.AgentSettlementWithFlow{ SettlementId: mediumSettlement.Id, GenerateDataId: generateWxAdData.Id, Amount: v.AgentRevenue, BasicIncomeBefore: agentBasicIncomeBefore, BasicIncomeAfter: agentSettlement.BasicIncome, OtherIncomeBefore: agentOtherIncomeBefore, OtherIncomeAfter: agentSettlement.OtherIncome, Kind: enum.AgentSettlementWithFlowKindForBasicIncome, CreateAt: now.Format("2006-01-02 15:04:05"), UpdateAt: now.Format("2006-01-02 15:04:05"), }) if err != nil { _ = session.Rollback() return } } //4、修改 generate_wx_ad_data 记录中的 is_generate_report (是否已应用(0:未 1:已) ) generateWxAdData.IsGenerateReport = 1 _, err = generateWxAdDataDb.UpdateGenerateWxAdDataBySession(session, generateWxAdData, "is_generate_report") if err != nil { _ = session.Rollback() return } return session.Commit() }