代码初始化
This commit is contained in:
396
service/api_service.go
Normal file
396
service/api_service.go
Normal file
@@ -0,0 +1,396 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
entities "cid/entities"
|
||||
)
|
||||
|
||||
// APIService API服务接口
|
||||
type APIService interface {
|
||||
GetCampaignReport(params *entities.RequestParams) (*entities.APIResponse, error)
|
||||
GetCampaignReportByTimeRange(advertiserID int64, startTime, endTime int64) (*entities.APIResponse, error)
|
||||
GetAllCampaignReport(params *entities.RequestParams) (*entities.APIResponse, error)
|
||||
GetAllCampaignReportByTimeRange(advertiserID int64, startTime, endTime int64) (*entities.APIResponse, error)
|
||||
GetCampaignReportWithCallback(params *entities.RequestParams, callback func(*entities.APIResponse, error) bool) error
|
||||
}
|
||||
|
||||
// KuaishouAPIService 快手API服务实现
|
||||
type KuaishouAPIService struct {
|
||||
BaseURL string
|
||||
AccessToken string
|
||||
HTTPClient *http.Client
|
||||
MaxRetries int
|
||||
RetryDelay time.Duration
|
||||
RateLimit time.Duration // 请求间隔,避免触发限流
|
||||
}
|
||||
|
||||
// NewKuaishouAPIService 创建API服务实例
|
||||
func NewKuaishouAPIService(accessToken string) *KuaishouAPIService {
|
||||
return &KuaishouAPIService{
|
||||
BaseURL: "https://ad.e.kuaishou.com/rest/openapi/gw/esp/report",
|
||||
AccessToken: accessToken,
|
||||
HTTPClient: &http.Client{
|
||||
Timeout: 30 * time.Second,
|
||||
},
|
||||
MaxRetries: 3,
|
||||
RetryDelay: 2 * time.Second,
|
||||
RateLimit: 200 * time.Millisecond, // 默认200ms间隔
|
||||
}
|
||||
}
|
||||
|
||||
// SetRateLimit 设置请求间隔
|
||||
func (s *KuaishouAPIService) SetRateLimit(delay time.Duration) {
|
||||
s.RateLimit = delay
|
||||
}
|
||||
|
||||
// GetCampaignReport 获取广告计划报表(单页)
|
||||
func (s *KuaishouAPIService) GetCampaignReport(params *entities.RequestParams) (*entities.APIResponse, error) {
|
||||
for retry := 0; retry <= s.MaxRetries; retry++ {
|
||||
response, err := s.doRequest(params)
|
||||
if err == nil {
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// 判断是否重试
|
||||
if retry < s.MaxRetries {
|
||||
time.Sleep(s.RetryDelay)
|
||||
continue
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("请求失败,已达到最大重试次数")
|
||||
}
|
||||
|
||||
// doRequest 执行实际请求
|
||||
func (s *KuaishouAPIService) doRequest(params *entities.RequestParams) (*entities.APIResponse, error) {
|
||||
// 序列化请求参数
|
||||
jsonData, err := json.Marshal(params)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("序列化失败: %v", err)
|
||||
}
|
||||
|
||||
// 创建HTTP请求
|
||||
url := fmt.Sprintf("%s/campaignReport", s.BaseURL)
|
||||
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("创建请求失败: %v", err)
|
||||
}
|
||||
|
||||
// 设置请求头
|
||||
s.setHeaders(req)
|
||||
|
||||
// 发送请求
|
||||
resp, err := s.HTTPClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("请求失败: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// 检查HTTP状态码
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
body, _ := ioutil.ReadAll(resp.Body)
|
||||
return nil, fmt.Errorf("HTTP状态码错误: %d, 响应: %s", resp.StatusCode, string(body))
|
||||
}
|
||||
|
||||
// 读取响应
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("读取响应失败: %v", err)
|
||||
}
|
||||
|
||||
// 解析响应
|
||||
var apiResponse entities.APIResponse
|
||||
err = json.Unmarshal(body, &apiResponse)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("解析响应失败: %v", err)
|
||||
}
|
||||
|
||||
// 检查API返回码
|
||||
if apiResponse.Code != 0 {
|
||||
return nil, fmt.Errorf("API返回错误: %s (code: %d)", apiResponse.Message, apiResponse.Code)
|
||||
}
|
||||
|
||||
return &apiResponse, nil
|
||||
}
|
||||
|
||||
// GetAllCampaignReport 获取所有分页数据
|
||||
func (s *KuaishouAPIService) GetAllCampaignReport(params *entities.RequestParams) (*entities.APIResponse, error) {
|
||||
// 1. 先获取第一页数据,得到总数
|
||||
params.ResetPage()
|
||||
firstPage, err := s.GetCampaignReport(params)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取第一页数据失败: %v", err)
|
||||
}
|
||||
|
||||
if firstPage.Data == nil {
|
||||
return firstPage, nil // 没有数据
|
||||
}
|
||||
|
||||
totalCount := firstPage.Data.TotalCount
|
||||
pageSize := params.PageInfo.PageSize
|
||||
|
||||
// 2. 如果只有一页,直接返回
|
||||
if totalCount <= pageSize {
|
||||
return firstPage, nil
|
||||
}
|
||||
|
||||
// 3. 计算总页数
|
||||
totalPages := int(math.Ceil(float64(totalCount) / float64(pageSize)))
|
||||
|
||||
// 4. 创建结果集
|
||||
allResponses := make([]*entities.APIResponse, 0, totalPages)
|
||||
allResponses = append(allResponses, firstPage)
|
||||
|
||||
// 5. 并发获取剩余页数据
|
||||
pageChan := make(chan *pageResult, totalPages-1)
|
||||
|
||||
// 启动goroutine获取剩余页
|
||||
for page := 2; page <= totalPages; page++ {
|
||||
go func(currentPage int) {
|
||||
// 复制参数并设置页码
|
||||
pageParams := *params
|
||||
pageParams.PageInfo = &entities.PageInfo{
|
||||
CurrentPage: currentPage,
|
||||
PageSize: pageSize,
|
||||
}
|
||||
|
||||
response, err := s.GetCampaignReport(&pageParams)
|
||||
pageChan <- &pageResult{
|
||||
Page: currentPage,
|
||||
Response: response,
|
||||
Error: err,
|
||||
}
|
||||
|
||||
// 控制请求频率
|
||||
time.Sleep(s.RateLimit)
|
||||
}(page)
|
||||
}
|
||||
|
||||
// 6. 收集结果
|
||||
errors := make([]error, 0)
|
||||
for i := 0; i < totalPages-1; i++ {
|
||||
result := <-pageChan
|
||||
if result.Error != nil {
|
||||
errors = append(errors, fmt.Errorf("第%d页获取失败: %v", result.Page, result.Error))
|
||||
} else {
|
||||
allResponses = append(allResponses, result.Response)
|
||||
}
|
||||
}
|
||||
|
||||
// 7. 合并数据
|
||||
mergedResponse := entities.MergeData(allResponses)
|
||||
|
||||
// 8. 如果有错误,返回错误信息
|
||||
if len(errors) > 0 {
|
||||
// 可以记录错误日志,但继续返回已获取的数据
|
||||
fmt.Printf("部分页面获取失败: %v\n", errors)
|
||||
}
|
||||
|
||||
return mergedResponse, nil
|
||||
}
|
||||
|
||||
// GetAllCampaignReportByTimeRange 根据时间范围获取所有数据
|
||||
func (s *KuaishouAPIService) GetAllCampaignReportByTimeRange(advertiserID int64, startTime, endTime int64) (*entities.APIResponse, error) {
|
||||
params := entities.NewRequestParams()
|
||||
params.AdvertiserID = advertiserID
|
||||
params.StartTime = startTime
|
||||
params.EndTime = endTime
|
||||
|
||||
return s.GetAllCampaignReport(params)
|
||||
}
|
||||
|
||||
// GetCampaignReportWithCallback 使用回调函数获取所有数据(流式处理,避免内存占用过大)
|
||||
func (s *KuaishouAPIService) GetCampaignReportWithCallback(params *entities.RequestParams, callback func(*entities.APIResponse, error) bool) error {
|
||||
// 1. 先获取第一页数据,得到总数
|
||||
params.ResetPage()
|
||||
firstPage, err := s.GetCampaignReport(params)
|
||||
if err != nil {
|
||||
return fmt.Errorf("获取第一页数据失败: %v", err)
|
||||
}
|
||||
|
||||
// 调用回调处理第一页
|
||||
if !callback(firstPage, nil) {
|
||||
return nil // 回调要求停止
|
||||
}
|
||||
|
||||
if firstPage.Data == nil || firstPage.Data.TotalCount <= params.PageInfo.PageSize {
|
||||
return nil // 只有一页
|
||||
}
|
||||
|
||||
totalCount := firstPage.Data.TotalCount
|
||||
pageSize := params.PageInfo.PageSize
|
||||
totalPages := int(math.Ceil(float64(totalCount) / float64(pageSize)))
|
||||
|
||||
// 2. 顺序获取剩余页数据(避免并发导致API限流)
|
||||
for page := 2; page <= totalPages; page++ {
|
||||
// 复制参数并设置页码
|
||||
pageParams := *params
|
||||
pageParams.PageInfo = &entities.PageInfo{
|
||||
CurrentPage: page,
|
||||
PageSize: pageSize,
|
||||
}
|
||||
|
||||
response, err := s.GetCampaignReport(&pageParams)
|
||||
if !callback(response, err) {
|
||||
return nil // 回调要求停止
|
||||
}
|
||||
|
||||
// 控制请求频率
|
||||
time.Sleep(s.RateLimit)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetCampaignReportSequential 顺序获取所有数据(简单实现)
|
||||
func (s *KuaishouAPIService) GetCampaignReportSequential(params *entities.RequestParams) (*entities.APIResponse, error) {
|
||||
// 1. 先获取第一页数据,得到总数
|
||||
params.ResetPage()
|
||||
firstPage, err := s.GetCampaignReport(params)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取第一页数据失败: %v", err)
|
||||
}
|
||||
|
||||
if firstPage.Data == nil {
|
||||
return firstPage, nil
|
||||
}
|
||||
|
||||
totalCount := firstPage.Data.TotalCount
|
||||
pageSize := params.PageInfo.PageSize
|
||||
|
||||
// 2. 如果只有一页,直接返回
|
||||
if totalCount <= pageSize {
|
||||
return firstPage, nil
|
||||
}
|
||||
|
||||
// 3. 顺序获取所有数据
|
||||
allDetails := make([]*entities.ReportDetail, 0, totalCount)
|
||||
if firstPage.Data.Detail != nil {
|
||||
allDetails = append(allDetails, firstPage.Data.Detail...)
|
||||
}
|
||||
|
||||
totalPages := int(math.Ceil(float64(totalCount) / float64(pageSize)))
|
||||
|
||||
for page := 2; page <= totalPages; page++ {
|
||||
// 复制参数并设置页码
|
||||
pageParams := *params
|
||||
pageParams.PageInfo = &entities.PageInfo{
|
||||
CurrentPage: page,
|
||||
PageSize: pageSize,
|
||||
}
|
||||
|
||||
response, err := s.GetCampaignReport(&pageParams)
|
||||
if err != nil {
|
||||
// 记录错误但继续获取
|
||||
fmt.Printf("第%d页获取失败: %v\n", page, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if response.Data != nil && response.Data.Detail != nil {
|
||||
allDetails = append(allDetails, response.Data.Detail...)
|
||||
}
|
||||
|
||||
// 控制请求频率
|
||||
time.Sleep(s.RateLimit)
|
||||
}
|
||||
|
||||
// 4. 构建完整响应
|
||||
completeResponse := &entities.APIResponse{
|
||||
Code: firstPage.Code,
|
||||
Message: firstPage.Message,
|
||||
Data: &entities.ReportData{
|
||||
Sum: firstPage.Data.Sum,
|
||||
Detail: allDetails,
|
||||
TotalCount: totalCount,
|
||||
},
|
||||
}
|
||||
|
||||
return completeResponse, nil
|
||||
}
|
||||
|
||||
// setHeaders 设置请求头
|
||||
func (s *KuaishouAPIService) setHeaders(req *http.Request) {
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Accept", "application/json")
|
||||
if s.AccessToken != "" {
|
||||
req.Header.Set("Access-Token", s.AccessToken)
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", s.AccessToken))
|
||||
}
|
||||
}
|
||||
|
||||
// pageResult 分页结果
|
||||
type pageResult struct {
|
||||
Page int
|
||||
Response *entities.APIResponse
|
||||
Error error
|
||||
}
|
||||
|
||||
// ReportStatistics 报表统计
|
||||
type ReportStatistics struct {
|
||||
TotalImpression int64
|
||||
TotalClick int64
|
||||
TotalCost float64
|
||||
TotalGMV float64
|
||||
TotalT0GMV float64
|
||||
TotalT0OrderCnt int64
|
||||
PageCount int
|
||||
RecordCount int
|
||||
}
|
||||
|
||||
// CalculateStatistics 计算统计信息
|
||||
func CalculateStatistics(response *entities.APIResponse) *ReportStatistics {
|
||||
stats := &ReportStatistics{}
|
||||
|
||||
if response.Data == nil {
|
||||
return stats
|
||||
}
|
||||
|
||||
stats.PageCount = 1 // 默认值
|
||||
stats.RecordCount = response.Data.TotalCount
|
||||
|
||||
if response.Data.Detail != nil {
|
||||
for _, detail := range response.Data.Detail {
|
||||
stats.TotalImpression += detail.Impression
|
||||
stats.TotalClick += detail.Click
|
||||
stats.TotalCost += detail.CostTotal
|
||||
stats.TotalGMV += detail.GMV
|
||||
stats.TotalT0GMV += detail.T0GMV
|
||||
stats.TotalT0OrderCnt += detail.T0OrderCnt
|
||||
}
|
||||
}
|
||||
|
||||
return stats
|
||||
}
|
||||
|
||||
// GetAverageMetrics 获取平均指标
|
||||
func (stats *ReportStatistics) GetAverageMetrics() map[string]float64 {
|
||||
metrics := make(map[string]float64)
|
||||
|
||||
if stats.TotalImpression > 0 {
|
||||
metrics["ctr"] = float64(stats.TotalClick) / float64(stats.TotalImpression) * 100
|
||||
}
|
||||
|
||||
if stats.TotalClick > 0 {
|
||||
metrics["cpc"] = stats.TotalCost / float64(stats.TotalClick)
|
||||
}
|
||||
|
||||
if stats.TotalCost > 0 {
|
||||
metrics["roi"] = stats.TotalGMV / stats.TotalCost
|
||||
metrics["t0_roi"] = stats.TotalT0GMV / stats.TotalCost
|
||||
}
|
||||
|
||||
if stats.TotalImpression > 0 {
|
||||
metrics["cpm"] = stats.TotalCost / float64(stats.TotalImpression) * 1000
|
||||
}
|
||||
|
||||
return metrics
|
||||
}
|
||||
113
service/copydata/api_account_report_service.go
Normal file
113
service/copydata/api_account_report_service.go
Normal file
@@ -0,0 +1,113 @@
|
||||
package copydata
|
||||
|
||||
import (
|
||||
dao "cid/dao/copydata"
|
||||
dto "cid/model/dto/copydata"
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
type cidAccountReportDetailService struct{}
|
||||
|
||||
// CidAccountReportDetail 广告数据报表详情服务
|
||||
var CidAccountReportDetail = new(cidAccountReportDetailService)
|
||||
|
||||
// Create 创建广告数据报表详情
|
||||
func (s *cidAccountReportDetailService) Create(ctx context.Context, req *dto.CidAccountReportDetailItem) (res *dto.CreateCidAccountReportDetailRes, err error) {
|
||||
// 验证必要字段
|
||||
if req.DataType == "" {
|
||||
return nil, errors.New("数据类型不能为空")
|
||||
}
|
||||
if req.ReportDateStr == "" {
|
||||
return nil, errors.New("报告日期不能为空")
|
||||
}
|
||||
|
||||
// 插入数据库
|
||||
id, err := dao.CidAccountReportDetail.Insert(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res = &dto.CreateCidAccountReportDetailRes{
|
||||
Id: id,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// BatchCreate 批量创建广告数据报表详情
|
||||
func (s *cidAccountReportDetailService) BatchCreate(ctx context.Context, req *dto.BatchCreateCidAccountReportDetailReq) (res *dto.BatchCreateCidAccountReportDetailRes, err error) {
|
||||
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
|
||||
// 验证数据
|
||||
if len(req.Items) == 0 {
|
||||
return nil, errors.New("批量创建数据不能为空")
|
||||
}
|
||||
|
||||
//// 验证每条数据
|
||||
//for i, item := range req.Items {
|
||||
// if item.DataType == "" {
|
||||
// return nil, errors.New("第" + string(rune(i+1)) + "条数据的数据类型不能为空")
|
||||
// }
|
||||
// if item.ReportDateStr == "" {
|
||||
// return nil, errors.New("第" + string(rune(i+1)) + "条数据的报告日期不能为空")
|
||||
// }
|
||||
//}
|
||||
|
||||
// 批量插入数据库
|
||||
successCount, failCount, failedIndexes, err := dao.CidAccountReportDetail.BatchInsert(ctx, req.Items)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res = &dto.BatchCreateCidAccountReportDetailRes{
|
||||
SuccessCount: successCount,
|
||||
FailCount: failCount,
|
||||
FailedItems: failedIndexes,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Create 创建广告数据报表汇总
|
||||
func (s *cidAccountReportDetailService) CreateSum(ctx context.Context, req *dto.CidAccountReportSumItem) (res *dto.CreateCidAccountReportSumRes, err error) {
|
||||
// 验证必要字段
|
||||
if req.DataType == "" {
|
||||
return nil, errors.New("数据类型不能为空")
|
||||
}
|
||||
if req.ReportDateStr == "" {
|
||||
return nil, errors.New("报告日期不能为空")
|
||||
}
|
||||
|
||||
// 插入数据库
|
||||
id, err := dao.CidAccountReportSum.Insert(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res = &dto.CreateCidAccountReportSumRes{
|
||||
Id: id,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// BatchCreate 批量创建广告数据报表汇总
|
||||
func (s *cidAccountReportDetailService) BatchCreateSum(ctx context.Context, req *dto.BatchCreateCidAccountReportSumReq) (res *dto.BatchCreateCidAccountReportSumRes, err error) {
|
||||
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
|
||||
// 验证数据
|
||||
if len(req.Items) == 0 {
|
||||
return nil, errors.New("批量创建数据不能为空")
|
||||
}
|
||||
|
||||
// 批量插入数据库
|
||||
successCount, failCount, failedIndexes, err := dao.CidAccountReportSum.BatchInsert(ctx, req.Items)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res = &dto.BatchCreateCidAccountReportSumRes{
|
||||
SuccessCount: successCount,
|
||||
FailCount: failCount,
|
||||
FailedItems: failedIndexes,
|
||||
}
|
||||
return
|
||||
}
|
||||
91
service/copydata/creative_report_sum_service.go
Normal file
91
service/copydata/creative_report_sum_service.go
Normal file
@@ -0,0 +1,91 @@
|
||||
package copydata
|
||||
|
||||
import (
|
||||
dao "cid/dao/copydata"
|
||||
dto "cid/model/dto/copydata"
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
type creativeReportSumService struct{}
|
||||
|
||||
// CreativeReportSum 广告效果指标表服务
|
||||
var CreativeReportSum = new(creativeReportSumService)
|
||||
|
||||
// Create 创建广告效果指标表
|
||||
func (s *creativeReportSumService) Create(ctx context.Context, req *dto.CreativeReportSumItem) (res *dto.CreateCreativeReportSumRes, err error) {
|
||||
// 验证必要字段
|
||||
if req.ReportDateStr == "" {
|
||||
return nil, errors.New("报告日期不能为空")
|
||||
}
|
||||
|
||||
// 插入数据库
|
||||
id, err := dao.CreativeReportSum.Insert(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res = &dto.CreateCreativeReportSumRes{
|
||||
Id: id,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// BatchCreate 批量创建广告效果指标表
|
||||
func (s *creativeReportSumService) BatchCreate(ctx context.Context, req *dto.BatchCreateCreativeReportSumReq) (res *dto.BatchCreateCreativeReportSumRes, err error) {
|
||||
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
|
||||
// 验证数据
|
||||
if len(req.Items) == 0 {
|
||||
return nil, errors.New("批量创建数据不能为空")
|
||||
}
|
||||
|
||||
// 批量插入数据库
|
||||
successCount, failCount, failedIndexes, err := dao.CreativeReportSum.BatchInsert(ctx, req.Items)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res = &dto.BatchCreateCreativeReportSumRes{
|
||||
SuccessCount: successCount,
|
||||
FailCount: failCount,
|
||||
FailedItems: failedIndexes,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *creativeReportSumService) CreateDetail(ctx context.Context, req *dto.CreativeReportDetailItem) (res *dto.CreateCreativeReportDetailRes, err error) {
|
||||
if req.ReportDateStr == "" {
|
||||
return nil, errors.New("报告日期不能为空")
|
||||
}
|
||||
|
||||
id, err := dao.CreativeReportDetail.Insert(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res = &dto.CreateCreativeReportDetailRes{
|
||||
Id: id,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *creativeReportSumService) BatchCreateDetail(ctx context.Context, req *dto.BatchCreateCreativeReportDetailReq) (res *dto.BatchCreateCreativeReportDetailRes, err error) {
|
||||
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
|
||||
if len(req.Items) == 0 {
|
||||
return nil, errors.New("批量创建数据不能为空")
|
||||
}
|
||||
|
||||
successCount, failCount, failedIndexes, err := dao.CreativeReportDetail.BatchInsert(ctx, req.Items)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res = &dto.BatchCreateCreativeReportDetailRes{
|
||||
SuccessCount: successCount,
|
||||
FailCount: failCount,
|
||||
FailedItems: failedIndexes,
|
||||
}
|
||||
return
|
||||
}
|
||||
261
service/copydata/material_report_service.go
Normal file
261
service/copydata/material_report_service.go
Normal file
@@ -0,0 +1,261 @@
|
||||
package copydata
|
||||
|
||||
import (
|
||||
dao "cid/dao/copydata"
|
||||
dto "cid/model/dto/copydata"
|
||||
entity "cid/model/entity/copydata"
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
type materialReportService struct{}
|
||||
|
||||
// MaterialReport 素材报表数据服务
|
||||
var MaterialReport = new(materialReportService)
|
||||
|
||||
// Create 创建素材报表数据
|
||||
func (s *materialReportService) Create(ctx context.Context, req *dto.MaterialReportItem) (res *dto.CreateMaterialReportRes, err error) {
|
||||
if req.ReportDateStr == "" {
|
||||
return nil, errors.New("报告日期不能为空")
|
||||
}
|
||||
|
||||
id, err := dao.MaterialReport.Insert(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res = &dto.CreateMaterialReportRes{
|
||||
Id: id,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// BatchCreate 批量创建素材报表数据
|
||||
func (s *materialReportService) BatchCreate(ctx context.Context, req *dto.BatchCreateMaterialReportReq) (res *dto.BatchCreateMaterialReportRes, err error) {
|
||||
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
|
||||
|
||||
if len(req.Items) == 0 {
|
||||
return nil, errors.New("批量创建数据不能为空")
|
||||
}
|
||||
|
||||
successCount, failCount, failedIndexes, err := dao.MaterialReport.BatchInsert(ctx, req.Items)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res = &dto.BatchCreateMaterialReportRes{
|
||||
SuccessCount: successCount,
|
||||
FailCount: failCount,
|
||||
FailedItems: failedIndexes,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// List 获取素材报表数据列表
|
||||
func (s *materialReportService) List(ctx context.Context, req *dto.ListMaterialReportReq) (res *dto.ListMaterialReportRes, err error) {
|
||||
list, total, err := dao.MaterialReport.List(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
items := make([]*dto.MaterialReportItem, len(list))
|
||||
for i, item := range list {
|
||||
items[i] = convertMaterialEntityToDTO(item)
|
||||
}
|
||||
|
||||
res = &dto.ListMaterialReportRes{
|
||||
List: items,
|
||||
Total: total,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// convertEntityToDTO 将实体转换为 DTO
|
||||
func convertMaterialEntityToDTO(entity *entity.MaterialReport) *dto.MaterialReportItem {
|
||||
return &dto.MaterialReportItem{
|
||||
CreatedBy: entity.CreatedBy,
|
||||
UpdatedBy: entity.UpdatedBy,
|
||||
T0OrderPaymentAmt: entity.T0OrderPaymentAmt,
|
||||
CreativeMaterialType: entity.CreativeMaterialType,
|
||||
LiveName: entity.LiveName,
|
||||
AuthorId: entity.AuthorId,
|
||||
PicUrl: entity.PicUrl,
|
||||
PicName: entity.PicName,
|
||||
PicId: entity.PicId,
|
||||
CoverUrl: entity.CoverUrl,
|
||||
CoverId: entity.CoverId,
|
||||
ItemOrderConversionRatio: entity.ItemOrderConversionRatio,
|
||||
ItemCardClickRatio: entity.ItemCardClickRatio,
|
||||
ItemCardClkCnt: entity.ItemCardClkCnt,
|
||||
LivePlayCntCost: entity.LivePlayCntCost,
|
||||
AdMerchantFollowCost: entity.AdMerchantFollowCost,
|
||||
AdMerchantFollow: entity.AdMerchantFollow,
|
||||
NetT0OrderCnt: entity.NetT0OrderCnt,
|
||||
NetT0Roi: entity.NetT0Roi,
|
||||
NetT0Gmv: entity.NetT0Gmv,
|
||||
PhotoName: entity.PhotoName,
|
||||
PhotoIdStr: entity.PhotoIdStr,
|
||||
PhotoId: entity.PhotoId,
|
||||
ModPriceSegment: entity.ModPriceSegment,
|
||||
AgeSegment: entity.AgeSegment,
|
||||
Province: entity.Province,
|
||||
Gender: entity.Gender,
|
||||
AdPhotoPlayedFiveRatio: entity.AdPhotoPlayedFiveRatio,
|
||||
AdPhotoPlayedThreeRatio: entity.AdPhotoPlayedThreeRatio,
|
||||
OrderSubmitRoi: entity.OrderSubmitRoi,
|
||||
OrderSubmitAmt: entity.OrderSubmitAmt,
|
||||
EventOrderSubmitCost: entity.EventOrderSubmitCost,
|
||||
EventOrderSubmit: entity.EventOrderSubmit,
|
||||
EventOrderPaidRoi: entity.EventOrderPaidRoi,
|
||||
EventAppInvoked: entity.EventAppInvoked,
|
||||
EventAddShoppingCart: entity.EventAddShoppingCart,
|
||||
ConversionNumCost: entity.ConversionNumCost,
|
||||
AdEffectivePlayNum: entity.AdEffectivePlayNum,
|
||||
AdItemClick: entity.AdItemClick,
|
||||
MerchantProductId: entity.MerchantProductId,
|
||||
CostTotal: entity.CostTotal,
|
||||
AdShow: entity.AdShow,
|
||||
AdShow1kCost: entity.AdShow1kCost,
|
||||
Impression: entity.Impression,
|
||||
PhotoClick: entity.PhotoClick,
|
||||
PhotoClickRatio: entity.PhotoClickRatio,
|
||||
Click: entity.Click,
|
||||
ActionbarClick: entity.ActionbarClick,
|
||||
ActionbarClickCost: entity.ActionbarClickCost,
|
||||
EspClickRatio: entity.EspClickRatio,
|
||||
ActionRatio: entity.ActionRatio,
|
||||
AdItemCount: entity.AdItemCount,
|
||||
EspLivePlayedSeconds: entity.EspLivePlayedSeconds,
|
||||
PlayedThreeSeconds: entity.PlayedThreeSeconds,
|
||||
Play3sRatio: entity.Play3sRatio,
|
||||
PlayedFiveSeconds: entity.PlayedFiveSeconds,
|
||||
Play5sRatio: entity.Play5sRatio,
|
||||
PlayedEnd: entity.PlayedEnd,
|
||||
PlayEndRatio: entity.PlayEndRatio,
|
||||
Share: entity.Share,
|
||||
Comment: entity.Comment,
|
||||
Likes: entity.Likes,
|
||||
Report: entity.Report,
|
||||
Block: entity.Block,
|
||||
ItemNegative: entity.ItemNegative,
|
||||
LiveShare: entity.LiveShare,
|
||||
LiveComment: entity.LiveComment,
|
||||
LiveReward: entity.LiveReward,
|
||||
EffectivePlayCount: entity.EffectivePlayCount,
|
||||
EffectivePlayRatio: entity.EffectivePlayRatio,
|
||||
ConversionNum: entity.ConversionNum,
|
||||
ConversionCostEsp: entity.ConversionCostEsp,
|
||||
Roi: entity.Roi,
|
||||
Gmv: entity.Gmv,
|
||||
T0Gmv: entity.T0Gmv,
|
||||
T1Gmv: entity.T1Gmv,
|
||||
T7Gmv: entity.T7Gmv,
|
||||
T15Gmv: entity.T15Gmv,
|
||||
T30Gmv: entity.T30Gmv,
|
||||
T0Roi: entity.T0Roi,
|
||||
T1Roi: entity.T1Roi,
|
||||
T7Roi: entity.T7Roi,
|
||||
T15Roi: entity.T15Roi,
|
||||
T30Roi: entity.T30Roi,
|
||||
PaiedOrder: entity.PaiedOrder,
|
||||
OrderRatio: entity.OrderRatio,
|
||||
T0OrderCnt: entity.T0OrderCnt,
|
||||
T0OrderCntCost: entity.T0OrderCntCost,
|
||||
T0OrderCntRatio: entity.T0OrderCntRatio,
|
||||
T1OrderCnt: entity.T1OrderCnt,
|
||||
T7OrderCnt: entity.T7OrderCnt,
|
||||
T15OrderCnt: entity.T15OrderCnt,
|
||||
T30OrderCnt: entity.T30OrderCnt,
|
||||
MerchantRecoFans: entity.MerchantRecoFans,
|
||||
T1Retention: entity.T1Retention,
|
||||
T7Retention: entity.T7Retention,
|
||||
T15Retention: entity.T15Retention,
|
||||
T30Retention: entity.T30Retention,
|
||||
T1RetentionRatio: entity.T1RetentionRatio,
|
||||
T7RetentionRatio: entity.T7RetentionRatio,
|
||||
T15RetentionRatio: entity.T15RetentionRatio,
|
||||
T30RetentionRatio: entity.T30RetentionRatio,
|
||||
ReservationSuccess: entity.ReservationSuccess,
|
||||
ReservationCost: entity.ReservationCost,
|
||||
StandardLivePlayedStarted: entity.StandardLivePlayedStarted,
|
||||
AdLivePlayCnt: entity.AdLivePlayCnt,
|
||||
AdLivePlayCntCost: entity.AdLivePlayCntCost,
|
||||
LiveAudienceCost: entity.LiveAudienceCost,
|
||||
LiveEventGoodsView: entity.LiveEventGoodsView,
|
||||
GoodsClickRatio: entity.GoodsClickRatio,
|
||||
DirectAttrPlatNewBuyerCnt: entity.DirectAttrPlatNewBuyerCnt,
|
||||
T30AttrPlatTotalBuyerCnt: entity.T30AttrPlatTotalBuyerCnt,
|
||||
DirectAttrSellerNewBuyerCnt: entity.DirectAttrSellerNewBuyerCnt,
|
||||
T30AttrSellerTotalBuyerCnt: entity.T30AttrSellerTotalBuyerCnt,
|
||||
T3Gmv: entity.T3Gmv,
|
||||
T3OrderCnt: entity.T3OrderCnt,
|
||||
T3Roi: entity.T3Roi,
|
||||
T7IndirectOrderAmt: entity.T7IndirectOrderAmt,
|
||||
T7IndirectOrderCnt: entity.T7IndirectOrderCnt,
|
||||
FansT0GmvPerFans: entity.FansT0GmvPerFans,
|
||||
FansT3GmvPerFans: entity.FansT3GmvPerFans,
|
||||
FansT7GmvPerFans: entity.FansT7GmvPerFans,
|
||||
FansT15GmvPerFans: entity.FansT15GmvPerFans,
|
||||
FansT30GmvPerFans: entity.FansT30GmvPerFans,
|
||||
RecoFansCost: entity.RecoFansCost,
|
||||
QcpxWhiteboxDirectOrderPaymentAmt: entity.QcpxWhiteboxDirectOrderPaymentAmt,
|
||||
QcpxWhiteboxDirectOrderCnt: entity.QcpxWhiteboxDirectOrderCnt,
|
||||
FansT0Gmv: entity.FansT0Gmv,
|
||||
FansT1Gmv: entity.FansT1Gmv,
|
||||
FansT7Gmv: entity.FansT7Gmv,
|
||||
FansT15Gmv: entity.FansT15Gmv,
|
||||
FansT30Gmv: entity.FansT30Gmv,
|
||||
FansT0Roi: entity.FansT0Roi,
|
||||
FansT1Roi: entity.FansT1Roi,
|
||||
FansT7Roi: entity.FansT7Roi,
|
||||
FansT15Roi: entity.FansT15Roi,
|
||||
FansT30Roi: entity.FansT30Roi,
|
||||
T0ShopNewBuyerOrderPaymentAmt: entity.T0ShopNewBuyerOrderPaymentAmt,
|
||||
T1ShopNewBuyerOrderPaymentAmt: entity.T1ShopNewBuyerOrderPaymentAmt,
|
||||
T3ShopNewBuyerOrderPaymentAmt: entity.T3ShopNewBuyerOrderPaymentAmt,
|
||||
T7ShopNewBuyerOrderPaymentAmt: entity.T7ShopNewBuyerOrderPaymentAmt,
|
||||
T15ShopNewBuyerOrderPaymentAmt: entity.T15ShopNewBuyerOrderPaymentAmt,
|
||||
T30ShopNewBuyerOrderPaymentAmt: entity.T30ShopNewBuyerOrderPaymentAmt,
|
||||
T0ShopNewBuyerOrderCnt: entity.T0ShopNewBuyerOrderCnt,
|
||||
T1ShopNewBuyerOrderCnt: entity.T1ShopNewBuyerOrderCnt,
|
||||
T3ShopNewBuyerOrderCnt: entity.T3ShopNewBuyerOrderCnt,
|
||||
T7ShopNewBuyerOrderCnt: entity.T7ShopNewBuyerOrderCnt,
|
||||
T15ShopNewBuyerOrderCnt: entity.T15ShopNewBuyerOrderCnt,
|
||||
T30ShopNewBuyerOrderCnt: entity.T30ShopNewBuyerOrderCnt,
|
||||
T1NewBuyerRepurchaseRatio: entity.T1NewBuyerRepurchaseRatio,
|
||||
T3NewBuyerRepurchaseRatio: entity.T3NewBuyerRepurchaseRatio,
|
||||
T7NewBuyerRepurchaseRatio: entity.T7NewBuyerRepurchaseRatio,
|
||||
T15NewBuyerRepurchaseRatio: entity.T15NewBuyerRepurchaseRatio,
|
||||
T30NewBuyerRepurchaseRatio: entity.T30NewBuyerRepurchaseRatio,
|
||||
T0ShopNewBuyerRoi: entity.T0ShopNewBuyerRoi,
|
||||
T1ShopNewBuyerRoi: entity.T1ShopNewBuyerRoi,
|
||||
T3ShopNewBuyerRoi: entity.T3ShopNewBuyerRoi,
|
||||
T7ShopNewBuyerRoi: entity.T7ShopNewBuyerRoi,
|
||||
T15ShopNewBuyerRoi: entity.T15ShopNewBuyerRoi,
|
||||
T30ShopNewBuyerRoi: entity.T30ShopNewBuyerRoi,
|
||||
CreateCardOrderCnt: entity.CreateCardOrderCnt,
|
||||
ForwardTsCreateCardOrderCnt: entity.ForwardTsCreateCardOrderCnt,
|
||||
CreateCardOrderCost: entity.CreateCardOrderCost,
|
||||
ForwardTsCreateCardOrderCost: entity.ForwardTsCreateCardOrderCost,
|
||||
ActivateCardOrderCnt: entity.ActivateCardOrderCnt,
|
||||
ForwardTsActivateCardOrderCnt: entity.ForwardTsActivateCardOrderCnt,
|
||||
ActivateCardOrderCost: entity.ActivateCardOrderCost,
|
||||
ForwardTsActivateCardOrderCost: entity.ForwardTsActivateCardOrderCost,
|
||||
CreateCardOrderRatio: entity.CreateCardOrderRatio,
|
||||
ForwardTsCreateCardOrderRatio: entity.ForwardTsCreateCardOrderRatio,
|
||||
ActivateCardOrderCntRatio: entity.ActivateCardOrderCntRatio,
|
||||
ForwardTsActivateCardOrderRatio: entity.ForwardTsActivateCardOrderRatio,
|
||||
LivePlayCnt: entity.LivePlayCnt,
|
||||
ItemEntranceClkCnt: entity.ItemEntranceClkCnt,
|
||||
ShowCnt: entity.ShowCnt,
|
||||
ReportDateStr: entity.ReportDateStr,
|
||||
CampaignId: entity.CampaignId,
|
||||
CampaignName: entity.CampaignName,
|
||||
UnitId: entity.UnitId,
|
||||
UnitName: entity.UnitName,
|
||||
CreativeId: entity.CreativeId,
|
||||
CreativeName: entity.CreativeName,
|
||||
}
|
||||
}
|
||||
237
service/copydata/population_report_service.go
Normal file
237
service/copydata/population_report_service.go
Normal file
@@ -0,0 +1,237 @@
|
||||
package copydata
|
||||
|
||||
import (
|
||||
dao "cid/dao/copydata"
|
||||
dto "cid/model/dto/copydata"
|
||||
entity "cid/model/entity/copydata"
|
||||
"context"
|
||||
"errors"
|
||||
)
|
||||
|
||||
var PopulationReportService = new(populationReportService)
|
||||
|
||||
type populationReportService struct{}
|
||||
|
||||
// Create 创建人群报表数据
|
||||
func (s *populationReportService) Create(ctx context.Context, req *dto.PopulationReportItem) (*dto.CreatePopulationReportRes, error) {
|
||||
if req.ReportDateStr == "" {
|
||||
return nil, errors.New("报告日期不能为空")
|
||||
}
|
||||
|
||||
id, err := dao.PopulationReport.Insert(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &dto.CreatePopulationReportRes{Id: id}, nil
|
||||
}
|
||||
|
||||
// BatchCreate 批量创建人群报表数据
|
||||
func (s *populationReportService) BatchCreate(ctx context.Context, req []*dto.PopulationReportItem) (*dto.BatchCreatePopulationReportRes, error) {
|
||||
if len(req) == 0 {
|
||||
return nil, errors.New("批量创建数据不能为空")
|
||||
}
|
||||
|
||||
successCount, failCount, failedIndexes, err := dao.PopulationReport.BatchInsert(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &dto.BatchCreatePopulationReportRes{
|
||||
SuccessCount: successCount,
|
||||
FailCount: failCount,
|
||||
FailedItems: failedIndexes,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// List 查询人群报表数据列表
|
||||
func (s *populationReportService) List(ctx context.Context, req *dto.ListPopulationReportReq) (*dto.ListPopulationReportRes, error) {
|
||||
list, total, err := dao.PopulationReport.List(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 转换为 DTO
|
||||
items := s.convertToDTOs(list)
|
||||
|
||||
return &dto.ListPopulationReportRes{
|
||||
List: items,
|
||||
Total: total,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// convertToDTOs 将实体列表转换为 DTO 列表
|
||||
func (s *populationReportService) convertToDTOs(entities []*entity.PopulationReport) []*dto.PopulationReportItem {
|
||||
items := make([]*dto.PopulationReportItem, 0, len(entities))
|
||||
for _, e := range entities {
|
||||
items = append(items, s.convertToDTO(e))
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
// convertToDTO 将实体转换为 DTO
|
||||
func (s *populationReportService) convertToDTO(e *entity.PopulationReport) *dto.PopulationReportItem {
|
||||
return &dto.PopulationReportItem{
|
||||
PhotoName: e.PhotoName,
|
||||
PhotoIdStr: e.PhotoIdStr,
|
||||
PhotoId: e.PhotoId,
|
||||
ModPriceSegment: e.ModPriceSegment,
|
||||
AgeSegment: e.AgeSegment,
|
||||
Province: e.Province,
|
||||
Gender: e.Gender,
|
||||
MerchantProductId: e.MerchantProductId,
|
||||
ReportDateStr: e.ReportDateStr,
|
||||
CampaignId: e.CampaignId,
|
||||
CampaignName: e.CampaignName,
|
||||
UnitId: e.UnitId,
|
||||
UnitName: e.UnitName,
|
||||
CreativeId: e.CreativeId,
|
||||
CreativeName: e.CreativeName,
|
||||
AdPhotoPlayedFiveRatio: e.AdPhotoPlayedFiveRatio,
|
||||
AdPhotoPlayedThreeRatio: e.AdPhotoPlayedThreeRatio,
|
||||
OrderSubmitRoi: e.OrderSubmitRoi,
|
||||
OrderSubmitAmt: e.OrderSubmitAmt,
|
||||
EventOrderSubmitCost: e.EventOrderSubmitCost,
|
||||
EventOrderSubmit: e.EventOrderSubmit,
|
||||
EventOrderPaidRoi: e.EventOrderPaidRoi,
|
||||
EventAppInvoked: e.EventAppInvoked,
|
||||
EventAddShoppingCart: e.EventAddShoppingCart,
|
||||
ConversionNumCost: e.ConversionNumCost,
|
||||
AdEffectivePlayNum: e.AdEffectivePlayNum,
|
||||
AdItemClick: e.AdItemClick,
|
||||
CostTotal: e.CostTotal,
|
||||
AdShow: e.AdShow,
|
||||
AdShow1kCost: e.AdShow1kCost,
|
||||
Impression: e.Impression,
|
||||
PhotoClick: e.PhotoClick,
|
||||
PhotoClickRatio: e.PhotoClickRatio,
|
||||
Click: e.Click,
|
||||
ActionbarClick: e.ActionbarClick,
|
||||
ActionbarClickCost: e.ActionbarClickCost,
|
||||
EspClickRatio: e.EspClickRatio,
|
||||
ActionRatio: e.ActionRatio,
|
||||
AdItemClickCount: e.AdItemClickCount,
|
||||
EspLivePlayedSeconds: e.EspLivePlayedSeconds,
|
||||
PlayedThreeSeconds: e.PlayedThreeSeconds,
|
||||
Play3sRatio: e.Play3sRatio,
|
||||
PlayedFiveSeconds: e.PlayedFiveSeconds,
|
||||
Play5sRatio: e.Play5sRatio,
|
||||
PlayedEnd: e.PlayedEnd,
|
||||
PlayEndRatio: e.PlayEndRatio,
|
||||
Share: e.Share,
|
||||
Comment: e.Comment,
|
||||
Likes: e.Likes,
|
||||
Report: e.Report,
|
||||
Block: e.Block,
|
||||
ItemNegative: e.ItemNegative,
|
||||
LiveShare: e.LiveShare,
|
||||
LiveComment: e.LiveComment,
|
||||
LiveReward: e.LiveReward,
|
||||
EffectivePlayCount: e.EffectivePlayCount,
|
||||
EffectivePlayRatio: e.EffectivePlayRatio,
|
||||
ConversionNum: e.ConversionNum,
|
||||
ConversionCostEsp: e.ConversionCostEsp,
|
||||
Roi: e.Roi,
|
||||
Gmv: e.Gmv,
|
||||
T0Gmv: e.T0Gmv,
|
||||
T1Gmv: e.T1Gmv,
|
||||
T3Gmv: e.T3Gmv,
|
||||
T7Gmv: e.T7Gmv,
|
||||
T15Gmv: e.T15Gmv,
|
||||
T30Gmv: e.T30Gmv,
|
||||
T0Roi: e.T0Roi,
|
||||
T1Roi: e.T1Roi,
|
||||
T3Roi: e.T3Roi,
|
||||
T7Roi: e.T7Roi,
|
||||
T15Roi: e.T15Roi,
|
||||
T30Roi: e.T30Roi,
|
||||
PaiedOrder: e.PaiedOrder,
|
||||
OrderRatio: e.OrderRatio,
|
||||
T0OrderCnt: e.T0OrderCnt,
|
||||
T0OrderCntCost: e.T0OrderCntCost,
|
||||
T0OrderCntRatio: e.T0OrderCntRatio,
|
||||
T1OrderCnt: e.T1OrderCnt,
|
||||
T7OrderCnt: e.T7OrderCnt,
|
||||
T15OrderCnt: e.T15OrderCnt,
|
||||
T30OrderCnt: e.T30OrderCnt,
|
||||
MerchantRecoFans: e.MerchantRecoFans,
|
||||
T1Retention: e.T1Retention,
|
||||
T7Retention: e.T7Retention,
|
||||
T15Retention: e.T15Retention,
|
||||
T30Retention: e.T30Retention,
|
||||
T1RetentionRatio: e.T1RetentionRatio,
|
||||
T7RetentionRatio: e.T7RetentionRatio,
|
||||
T15RetentionRatio: e.T15RetentionRatio,
|
||||
T30RetentionRatio: e.T30RetentionRatio,
|
||||
ReservationSuccess: e.ReservationSuccess,
|
||||
ReservationCost: e.ReservationCost,
|
||||
StandardLivePlayedStarted: e.StandardLivePlayedStarted,
|
||||
AdLivePlayCnt: e.AdLivePlayCnt,
|
||||
AdLivePlayCntCost: e.AdLivePlayCntCost,
|
||||
LiveAudienceCost: e.LiveAudienceCost,
|
||||
LiveEventGoodsView: e.LiveEventGoodsView,
|
||||
GoodsClickRatio: e.GoodsClickRatio,
|
||||
DirectAttrPlatNewBuyerCnt: e.DirectAttrPlatNewBuyerCnt,
|
||||
T30AttrPlatTotalBuyerCnt: e.T30AttrPlatTotalBuyerCnt,
|
||||
DirectAttrSellerNewBuyerCnt: e.DirectAttrSellerNewBuyerCnt,
|
||||
T30AttrSellerTotalBuyerCnt: e.T30AttrSellerTotalBuyerCnt,
|
||||
T7IndirectOrderAmt: e.T7IndirectOrderAmt,
|
||||
T7IndirectOrderCnt: e.T7IndirectOrderCnt,
|
||||
FansT0GmvPerFans: e.FansT0GmvPerFans,
|
||||
FansT3GmvPerFans: e.FansT3GmvPerFans,
|
||||
FansT7GmvPerFans: e.FansT7GmvPerFans,
|
||||
FansT15GmvPerFans: e.FansT15GmvPerFans,
|
||||
FansT30GmvPerFans: e.FansT30GmvPerFans,
|
||||
RecoFansCost: e.RecoFansCost,
|
||||
QcpxWhiteboxDirectOrderPaymentAmt: e.QcpxWhiteboxDirectOrderPaymentAmt,
|
||||
QcpxWhiteboxDirectOrderCnt: e.QcpxWhiteboxDirectOrderCnt,
|
||||
FansT0Gmv: e.FansT0Gmv,
|
||||
FansT1Gmv: e.FansT1Gmv,
|
||||
FansT7Gmv: e.FansT7Gmv,
|
||||
FansT15Gmv: e.FansT15Gmv,
|
||||
FansT30Gmv: e.FansT30Gmv,
|
||||
FansT0Roi: e.FansT0Roi,
|
||||
FansT1Roi: e.FansT1Roi,
|
||||
FansT7Roi: e.FansT7Roi,
|
||||
FansT15Roi: e.FansT15Roi,
|
||||
FansT30Roi: e.FansT30Roi,
|
||||
T0ShopNewBuyerOrderPaymentAmt: e.T0ShopNewBuyerOrderPaymentAmt,
|
||||
T1ShopNewBuyerOrderPaymentAmt: e.T1ShopNewBuyerOrderPaymentAmt,
|
||||
T3ShopNewBuyerOrderPaymentAmt: e.T3ShopNewBuyerOrderPaymentAmt,
|
||||
T7ShopNewBuyerOrderPaymentAmt: e.T7ShopNewBuyerOrderPaymentAmt,
|
||||
T15ShopNewBuyerOrderPaymentAmt: e.T15ShopNewBuyerOrderPaymentAmt,
|
||||
T30ShopNewBuyerOrderPaymentAmt: e.T30ShopNewBuyerOrderPaymentAmt,
|
||||
T0ShopNewBuyerOrderCnt: e.T0ShopNewBuyerOrderCnt,
|
||||
T1ShopNewBuyerOrderCnt: e.T1ShopNewBuyerOrderCnt,
|
||||
T3ShopNewBuyerOrderCnt: e.T3ShopNewBuyerOrderCnt,
|
||||
T7ShopNewBuyerOrderCnt: e.T7ShopNewBuyerOrderCnt,
|
||||
T15ShopNewBuyerOrderCnt: e.T15ShopNewBuyerOrderCnt,
|
||||
T30ShopNewBuyerOrderCnt: e.T30ShopNewBuyerOrderCnt,
|
||||
T1NewBuyerRepurchaseRatio: e.T1NewBuyerRepurchaseRatio,
|
||||
T3NewBuyerRepurchaseRatio: e.T3NewBuyerRepurchaseRatio,
|
||||
T7NewBuyerRepurchaseRatio: e.T7NewBuyerRepurchaseRatio,
|
||||
T15NewBuyerRepurchaseRatio: e.T15NewBuyerRepurchaseRatio,
|
||||
T30NewBuyerRepurchaseRatio: e.T30NewBuyerRepurchaseRatio,
|
||||
T0ShopNewBuyerRoi: e.T0ShopNewBuyerRoi,
|
||||
T1ShopNewBuyerRoi: e.T1ShopNewBuyerRoi,
|
||||
T3ShopNewBuyerRoi: e.T3ShopNewBuyerRoi,
|
||||
T7ShopNewBuyerRoi: e.T7ShopNewBuyerRoi,
|
||||
T15ShopNewBuyerRoi: e.T15ShopNewBuyerRoi,
|
||||
T30ShopNewBuyerRoi: e.T30ShopNewBuyerRoi,
|
||||
CreateCardOrderCnt: e.CreateCardOrderCnt,
|
||||
ForwardTsCreateCardOrderCnt: e.ForwardTsCreateCardOrderCnt,
|
||||
CreateCardOrderCost: e.CreateCardOrderCost,
|
||||
ForwardTsCreateCardOrderCost: e.ForwardTsCreateCardOrderCost,
|
||||
ActivateCardOrderCnt: e.ActivateCardOrderCnt,
|
||||
ForwardTsActivateCardOrderCnt: e.ForwardTsActivateCardOrderCnt,
|
||||
ActivateCardOrderCost: e.ActivateCardOrderCost,
|
||||
ForwardTsActivateCardOrderCost: e.ForwardTsActivateCardOrderCost,
|
||||
CreateCardOrderRatio: e.CreateCardOrderRatio,
|
||||
ForwardTsCreateCardOrderRatio: e.ForwardTsCreateCardOrderRatio,
|
||||
ActivateCardOrderCntRatio: e.ActivateCardOrderCntRatio,
|
||||
ForwardTsActivateCardOrderRatio: e.ForwardTsActivateCardOrderRatio,
|
||||
LivePlayCnt: e.LivePlayCnt,
|
||||
ItemEntranceClkCnt: e.ItemEntranceClkCnt,
|
||||
ShowCnt: e.ShowCnt,
|
||||
}
|
||||
}
|
||||
97
service/copydata/storewide_report_sum_service.go
Normal file
97
service/copydata/storewide_report_sum_service.go
Normal file
@@ -0,0 +1,97 @@
|
||||
package copydata
|
||||
|
||||
import (
|
||||
dao "cid/dao/copydata"
|
||||
dto "cid/model/dto/copydata"
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
type storewideReportService struct{}
|
||||
|
||||
// StorewideReportSum 广告效果指标表服务
|
||||
var StorewideReportSum = new(storewideReportService)
|
||||
|
||||
// Create 创建广告效果指标表
|
||||
func (s *storewideReportService) Create(ctx context.Context, req *dto.StorewideReportSumItem) (res *dto.CreateStorewideReportSumRes, err error) {
|
||||
// 验证必要字段
|
||||
if req.ReportDateStr == "" {
|
||||
return nil, errors.New("报告日期不能为空")
|
||||
}
|
||||
|
||||
// 插入数据库
|
||||
id, err := dao.StorewideReportSum.Insert(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res = &dto.CreateStorewideReportSumRes{
|
||||
Id: id,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// BatchCreate 批量创建广告效果指标表
|
||||
func (s *storewideReportService) BatchCreate(ctx context.Context, req *dto.BatchCreateStorewideReportSumReq) (res *dto.BatchCreateStorewideReportSumRes, err error) {
|
||||
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
|
||||
// 验证数据
|
||||
if len(req.Items) == 0 {
|
||||
return nil, errors.New("批量创建数据不能为空")
|
||||
}
|
||||
|
||||
// 批量插入数据库
|
||||
successCount, failCount, failedIndexes, err := dao.StorewideReportSum.BatchInsert(ctx, req.Items)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res = &dto.BatchCreateStorewideReportSumRes{
|
||||
SuccessCount: successCount,
|
||||
FailCount: failCount,
|
||||
FailedItems: failedIndexes,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Create 创建广告效果指标表
|
||||
func (s *storewideReportService) CreateDetail(ctx context.Context, req *dto.StorewideReportDetailItem) (res *dto.CreateStorewideReportDetailRes, err error) {
|
||||
// 验证必要字段
|
||||
if req.ReportDateStr == "" {
|
||||
return nil, errors.New("报告日期不能为空")
|
||||
}
|
||||
|
||||
// 插入数据库
|
||||
id, err := dao.StorewideReportDetail.Insert(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res = &dto.CreateStorewideReportDetailRes{
|
||||
Id: id,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// BatchCreate 批量创建广告效果指标表
|
||||
func (s *storewideReportService) BatchCreateDetail(ctx context.Context, req *dto.BatchCreateStorewideReportDetailReq) (res *dto.BatchCreateStorewideReportDetailRes, err error) {
|
||||
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
|
||||
// 验证数据
|
||||
if len(req.Items) == 0 {
|
||||
return nil, errors.New("批量创建数据不能为空")
|
||||
}
|
||||
|
||||
// 批量插入数据库
|
||||
successCount, failCount, failedIndexes, err := dao.StorewideReportDetail.BatchInsert(ctx, req.Items)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res = &dto.BatchCreateStorewideReportDetailRes{
|
||||
SuccessCount: successCount,
|
||||
FailCount: failCount,
|
||||
FailedItems: failedIndexes,
|
||||
}
|
||||
return
|
||||
}
|
||||
113
service/copydata/task_report_service.go
Normal file
113
service/copydata/task_report_service.go
Normal file
@@ -0,0 +1,113 @@
|
||||
package copydata
|
||||
|
||||
import (
|
||||
dao "cid/dao/copydata"
|
||||
dto "cid/model/dto/copydata"
|
||||
entity "cid/model/entity/copydata"
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
type taskReportService struct{}
|
||||
|
||||
// TaskReport 调控任务数据服务
|
||||
var TaskReport = new(taskReportService)
|
||||
|
||||
// Create 创建调控任务数据
|
||||
func (s *taskReportService) Create(ctx context.Context, req *dto.TaskReportItem) (res *dto.CreateTaskReportRes, err error) {
|
||||
// 验证必要字段
|
||||
if req.ReportDateStr == "" {
|
||||
return nil, errors.New("报告日期不能为空")
|
||||
}
|
||||
|
||||
// 插入数据库
|
||||
id, err := dao.TaskReport.Insert(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res = &dto.CreateTaskReportRes{
|
||||
Id: id,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// BatchCreate 批量创建调控任务数据
|
||||
func (s *taskReportService) BatchCreate(ctx context.Context, req *dto.BatchCreateTaskReportReq) (res *dto.BatchCreateTaskReportRes, err error) {
|
||||
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
|
||||
// 验证数据
|
||||
if len(req.Items) == 0 {
|
||||
return nil, errors.New("批量创建数据不能为空")
|
||||
}
|
||||
|
||||
// 批量插入数据库
|
||||
successCount, failCount, failedIndexes, err := dao.TaskReport.BatchInsert(ctx, req.Items)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res = &dto.BatchCreateTaskReportRes{
|
||||
SuccessCount: successCount,
|
||||
FailCount: failCount,
|
||||
FailedItems: failedIndexes,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// List 获取调控任务数据列表
|
||||
func (s *taskReportService) List(ctx context.Context, req *dto.ListTaskReportReq) (res *dto.ListTaskReportRes, err error) {
|
||||
list, total, err := dao.TaskReport.List(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 转换为 DTO 格式
|
||||
items := make([]*dto.TaskReportItem, len(list))
|
||||
for i, item := range list {
|
||||
items[i] = convertEntityToDTO(item)
|
||||
}
|
||||
|
||||
res = &dto.ListTaskReportRes{
|
||||
List: items,
|
||||
Total: total,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// convertEntityToDTO 将实体转换为 DTO
|
||||
func convertEntityToDTO(entity *entity.TaskReport) *dto.TaskReportItem {
|
||||
return &dto.TaskReportItem{
|
||||
ItemOrderConversionRatio: entity.ItemOrderConversionRatio,
|
||||
ItemCardClickRatio: entity.ItemCardClickRatio,
|
||||
ItemCardClkCnt: entity.ItemCardClkCnt,
|
||||
LivePlayCntCost: entity.LivePlayCntCost,
|
||||
AdMerchantFollowCost: entity.AdMerchantFollowCost,
|
||||
AdMerchantFollow: entity.AdMerchantFollow,
|
||||
NetT0OrderCnt: entity.NetT0OrderCnt,
|
||||
NetT0Roi: entity.NetT0Roi,
|
||||
NetT0Gmv: entity.NetT0Gmv,
|
||||
PhotoName: entity.PhotoName,
|
||||
PhotoId: entity.PhotoId,
|
||||
CostTotal: entity.CostTotal,
|
||||
T0Gmv: entity.T0Gmv,
|
||||
T0Roi: entity.T0Roi,
|
||||
T0OrderCnt: entity.T0OrderCnt,
|
||||
T0OrderCntCost: entity.T0OrderCntCost,
|
||||
FansT0Gmv: entity.FansT0Gmv,
|
||||
FansT1Gmv: entity.FansT1Gmv,
|
||||
FansT7Gmv: entity.FansT7Gmv,
|
||||
FansT15Gmv: entity.FansT15Gmv,
|
||||
FansT30Gmv: entity.FansT30Gmv,
|
||||
FansT0Roi: entity.FansT0Roi,
|
||||
FansT1Roi: entity.FansT1Roi,
|
||||
FansT7Roi: entity.FansT7Roi,
|
||||
FansT15Roi: entity.FansT15Roi,
|
||||
FansT30Roi: entity.FansT30Roi,
|
||||
LivePlayCnt: entity.LivePlayCnt,
|
||||
ItemEntranceClkCnt: entity.ItemEntranceClkCnt,
|
||||
ShowCnt: entity.ShowCnt,
|
||||
ReportDateStr: entity.ReportDateStr,
|
||||
}
|
||||
}
|
||||
90
service/copydata/unit_report_service.go
Normal file
90
service/copydata/unit_report_service.go
Normal file
@@ -0,0 +1,90 @@
|
||||
package copydata
|
||||
|
||||
import (
|
||||
dao "cid/dao/copydata"
|
||||
dto "cid/model/dto/copydata"
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
type unitReportSumService struct{}
|
||||
|
||||
// UnitReportSumService 广告效果指标服务
|
||||
var UnitReportSumService = new(unitReportSumService)
|
||||
|
||||
// Create 创建广告效果指标
|
||||
func (s *unitReportSumService) Create(ctx context.Context, req *dto.UnitReportSumItem) (res *dto.CreateUnitReportSumRes, err error) {
|
||||
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
|
||||
if req.ReportDateStr == "" {
|
||||
return nil, errors.New("报告日期不能为空")
|
||||
}
|
||||
|
||||
id, err := dao.UnitReportSum.Insert(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res = &dto.CreateUnitReportSumRes{
|
||||
Id: id,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// BatchCreate 批量创建广告效果指标
|
||||
func (s *unitReportSumService) BatchCreate(ctx context.Context, req *dto.BatchCreateUnitReportSumReq) (res *dto.BatchCreateUnitReportSumRes, err error) {
|
||||
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
|
||||
if len(req.Items) == 0 {
|
||||
return nil, errors.New("批量创建数据不能为空")
|
||||
}
|
||||
|
||||
successCount, failCount, failedIndexes, err := dao.UnitReportSum.BatchInsert(ctx, req.Items)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res = &dto.BatchCreateUnitReportSumRes{
|
||||
SuccessCount: successCount,
|
||||
FailCount: failCount,
|
||||
FailedItems: failedIndexes,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Create 创建广告效果指标详情
|
||||
func (s *unitReportSumService) CreateDetail(ctx context.Context, req *dto.UnitReportDetailItem) (res *dto.CreateUnitReportDetailRes, err error) {
|
||||
if req.ReportDateStr == "" {
|
||||
return nil, errors.New("报告日期不能为空")
|
||||
}
|
||||
|
||||
id, err := dao.UnitReportDetail.Insert(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res = &dto.CreateUnitReportDetailRes{
|
||||
Id: id,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// BatchCreate 批量创建广告效果指标详情
|
||||
func (s *unitReportSumService) BatchCreateDetail(ctx context.Context, req *dto.BatchCreateUnitReportDetailReq) (res *dto.BatchCreateUnitReportDetailRes, err error) {
|
||||
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
|
||||
if len(req.Items) == 0 {
|
||||
return nil, errors.New("批量创建数据不能为空")
|
||||
}
|
||||
|
||||
successCount, failCount, failedIndexes, err := dao.UnitReportDetail.BatchInsert(ctx, req.Items)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res = &dto.BatchCreateUnitReportDetailRes{
|
||||
SuccessCount: successCount,
|
||||
FailCount: failCount,
|
||||
FailedItems: failedIndexes,
|
||||
}
|
||||
return
|
||||
}
|
||||
305
service/dict/api_datasource_platform_service.go
Normal file
305
service/dict/api_datasource_platform_service.go
Normal file
@@ -0,0 +1,305 @@
|
||||
package dict
|
||||
|
||||
import (
|
||||
api_feature "cid/consts/api-feature"
|
||||
dao "cid/dao/dict"
|
||||
dto "cid/model/dto/dict"
|
||||
entity "cid/model/entity/dict"
|
||||
"context"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"github.com/olekukonko/errors"
|
||||
)
|
||||
|
||||
type datasourcePlatformService struct{}
|
||||
|
||||
// DatasourcePlatform 数据源平台服务
|
||||
var DatasourcePlatform = new(datasourcePlatformService)
|
||||
|
||||
// Create 创建数据源平台
|
||||
func (s *datasourcePlatformService) Create(ctx context.Context, req *dto.CreateDatasourcePlatformReq) (res *dto.CreateDatasourcePlatformRes, err error) {
|
||||
// 检查平台编码是否重复
|
||||
exists, err := dao.DatasourcePlatform.ExistsByPlatformCode(ctx, req.PlatformCode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if exists {
|
||||
return nil, errors.New("平台编码已存在")
|
||||
}
|
||||
|
||||
// 验证认证类型相关的必填字段
|
||||
if err = s.validateAuthFields(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 设置创建时间为当前时间
|
||||
if req.CreatedAt == "" {
|
||||
req.CreatedAt = strconv.FormatInt(time.Now().Unix(), 10)
|
||||
}
|
||||
req.UpdatedAt = req.CreatedAt
|
||||
|
||||
// 插入数据库
|
||||
id, err := dao.DatasourcePlatform.Insert(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res = &dto.CreateDatasourcePlatformRes{
|
||||
Id: id,
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// List 获取数据源平台列表
|
||||
func (s *datasourcePlatformService) List(ctx context.Context, req *dto.ListDatasourcePlatformReq) (res *dto.ListDatasourcePlatformRes, err error) {
|
||||
platformList, total, err := dao.DatasourcePlatform.List(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 组装响应数据
|
||||
list := make([]dto.DatasourcePlatformItem, 0, len(platformList))
|
||||
for _, item := range platformList {
|
||||
list = append(list, dto.DatasourcePlatformItem{
|
||||
Id: item.ID,
|
||||
PlatformCode: item.PlatformCode,
|
||||
PlatformName: item.PlatformName,
|
||||
Description: item.Description,
|
||||
Status: api_feature.PlatformStatus(item.Status),
|
||||
StatusName: s.getStatusName(api_feature.PlatformStatus(item.Status)),
|
||||
ApiBaseUrl: item.ApiBaseUrl,
|
||||
AuthType: item.AuthType,
|
||||
AuthTypeName: s.getAuthTypeName(item.AuthType),
|
||||
RateLimitPerMinute: item.RateLimitPerMinute,
|
||||
RateLimitPerHour: item.RateLimitPerHour,
|
||||
ConcurrencyLimit: item.ConcurrencyLimit,
|
||||
RequestTimeoutMs: item.RequestTimeoutMs,
|
||||
MaxRetries: item.MaxRetries,
|
||||
RetryDelayMs: item.RetryDelayMs,
|
||||
CreatedBy: item.CreatedBy,
|
||||
CreatedAt: item.CreatedAt.Unix(),
|
||||
UpdatedBy: item.UpdatedBy,
|
||||
UpdatedAt: item.UpdatedAt.Unix(),
|
||||
})
|
||||
}
|
||||
|
||||
res = &dto.ListDatasourcePlatformRes{
|
||||
List: list,
|
||||
Total: total,
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// GetOne 获取单个数据源平台
|
||||
func (s *datasourcePlatformService) GetOne(ctx context.Context, req *dto.GetDatasourcePlatformReq) (res *dto.GetDatasourcePlatformRes, err error) {
|
||||
platform, err := dao.DatasourcePlatform.GetOne(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if platform == nil {
|
||||
return nil, errors.New("数据源平台不存在")
|
||||
}
|
||||
|
||||
var platformEntity *entity.DatasourcePlatform
|
||||
if err = gconv.Struct(platform, &platformEntity); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 隐藏敏感信息
|
||||
platformEntity.Token = ""
|
||||
platformEntity.ClientSecret = ""
|
||||
platformEntity.ApiKey = ""
|
||||
|
||||
return &dto.GetDatasourcePlatformRes{
|
||||
DatasourcePlatform: platformEntity,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetByPlatformCode 根据平台编码获取数据源平台
|
||||
func (s *datasourcePlatformService) GetByPlatformCode(ctx context.Context, platformCode string) (res *entity.DatasourcePlatform, err error) {
|
||||
platform, err := dao.DatasourcePlatform.GetByPlatformCode(ctx, platformCode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if platform == nil {
|
||||
return nil, errors.New("数据源平台不存在")
|
||||
}
|
||||
return platform, nil
|
||||
}
|
||||
|
||||
// Update 更新数据源平台
|
||||
func (s *datasourcePlatformService) Update(ctx context.Context, req *dto.UpdateDatasourcePlatformReq) (err error) {
|
||||
// 检查平台是否存在
|
||||
exist, err := dao.DatasourcePlatform.GetOne(ctx, &dto.GetDatasourcePlatformReq{Id: req.Id})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if exist == nil {
|
||||
return errors.New("数据源平台不存在")
|
||||
}
|
||||
|
||||
// 如果修改了平台编码,检查新编码是否重复
|
||||
if req.PlatformCode != "" && req.PlatformCode != exist.PlatformCode {
|
||||
exists, err := dao.DatasourcePlatform.ExistsByPlatformCode(ctx, req.PlatformCode, req.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if exists {
|
||||
return errors.New("平台编码已存在")
|
||||
}
|
||||
}
|
||||
|
||||
// 验证认证类型相关的必填字段
|
||||
if req.AuthType != "" {
|
||||
authReq := &dto.CreateDatasourcePlatformReq{
|
||||
AuthType: req.AuthType,
|
||||
Token: req.Token,
|
||||
ApiKey: req.ApiKey,
|
||||
ClientId: req.ClientId,
|
||||
ClientSecret: req.ClientSecret,
|
||||
}
|
||||
if err = s.validateAuthFields(authReq); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// 设置更新时间
|
||||
req.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10)
|
||||
_, err = dao.DatasourcePlatform.Update(ctx, req)
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdateStatus 更新数据源平台状态
|
||||
func (s *datasourcePlatformService) UpdateStatus(ctx context.Context, req *dto.UpdateDatasourcePlatformStatusReq) (err error) {
|
||||
// 检查平台是否存在
|
||||
exist, err := dao.DatasourcePlatform.GetOne(ctx, &dto.GetDatasourcePlatformReq{Id: req.Id})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if exist == nil {
|
||||
return errors.New("数据源平台不存在")
|
||||
}
|
||||
|
||||
// 如果状态没有变化,直接返回
|
||||
if string(exist.Status) == req.Status.String() {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err = dao.DatasourcePlatform.UpdateStatus(ctx, req.Id, req.Status.String(), req.UpdatedBy)
|
||||
return err
|
||||
}
|
||||
|
||||
// Delete 删除数据源平台
|
||||
func (s *datasourcePlatformService) Delete(ctx context.Context, req *dto.DeleteDatasourcePlatformReq) (err error) {
|
||||
// 检查平台是否存在
|
||||
exist, err := dao.DatasourcePlatform.GetOne(ctx, &dto.GetDatasourcePlatformReq{Id: req.Id})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if exist == nil {
|
||||
return errors.New("数据源平台不存在")
|
||||
}
|
||||
|
||||
// TODO: 检查是否存在关联的数据,防止误删
|
||||
// 例如:检查该平台是否有关联的接口配置等
|
||||
|
||||
_, err = dao.DatasourcePlatform.Delete(ctx, req)
|
||||
return err
|
||||
}
|
||||
|
||||
// GetStatistics 获取平台统计信息
|
||||
func (s *datasourcePlatformService) GetStatistics(ctx context.Context) (res *dto.GetPlatformStatisticsRes, err error) {
|
||||
stats, err := dao.DatasourcePlatform.GetPlatformStatistics(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res = &dto.GetPlatformStatisticsRes{
|
||||
TotalPlatforms: int(stats["totalPlatforms"]),
|
||||
ActivePlatforms: int(stats["activePlatforms"]),
|
||||
InactivePlatforms: int(stats["inactivePlatforms"]),
|
||||
TokenAuthPlatforms: int(stats["TOKENAuthPlatforms"]),
|
||||
ApiKeyAuthPlatforms: int(stats["API_KEYAuthPlatforms"]),
|
||||
OAuth2AuthPlatforms: int(stats["OAUTH2AuthPlatforms"]),
|
||||
BasicAuthPlatforms: int(stats["BASICAuthPlatforms"]),
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// ListActivePlatforms 获取所有启用的平台
|
||||
func (s *datasourcePlatformService) ListActivePlatforms(ctx context.Context) (platforms []entity.DatasourcePlatform, err error) {
|
||||
return dao.DatasourcePlatform.ListActivePlatforms(ctx)
|
||||
}
|
||||
|
||||
// validateAuthFields 验证认证类型相关的必填字段
|
||||
func (s *datasourcePlatformService) validateAuthFields(req *dto.CreateDatasourcePlatformReq) error {
|
||||
switch req.AuthType {
|
||||
case "TOKEN":
|
||||
if req.Token == "" {
|
||||
return errors.New("TOKEN认证类型必须填写token字段")
|
||||
}
|
||||
case "API_KEY":
|
||||
if req.ApiKey == "" {
|
||||
return errors.New("API_KEY认证类型必须填写apiKey字段")
|
||||
}
|
||||
case "OAUTH2":
|
||||
if req.ClientId == "" || req.ClientSecret == "" {
|
||||
return errors.New("OAUTH2认证类型必须填写clientId和clientSecret字段")
|
||||
}
|
||||
case "BASIC":
|
||||
// BASIC认证通常需要用户名和密码,这里可以添加相应验证
|
||||
if req.Token == "" && req.ApiKey == "" {
|
||||
return errors.New("BASIC认证类型需要填写认证信息")
|
||||
}
|
||||
default:
|
||||
return errors.New("不支持的认证类型")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// performConnectionTest 执行连接测试(示例实现)
|
||||
func (s *datasourcePlatformService) performConnectionTest(platform *entity.DatasourcePlatform) (success bool, message string) {
|
||||
// 这里应该实现实际的连接测试逻辑
|
||||
// 例如:发送HTTP请求到api_base_url,验证响应
|
||||
|
||||
// 暂时返回模拟结果
|
||||
return true, "连接测试成功"
|
||||
}
|
||||
|
||||
// getStatusName 获取状态名称
|
||||
func (s *datasourcePlatformService) getStatusName(status api_feature.PlatformStatus) string {
|
||||
statusNames := map[api_feature.PlatformStatus]string{
|
||||
api_feature.PlatformStatusActive: "启用",
|
||||
api_feature.PlatformStatusInactive: "停用",
|
||||
}
|
||||
if name, ok := statusNames[status]; ok {
|
||||
return name
|
||||
}
|
||||
return string(status)
|
||||
}
|
||||
|
||||
// getAuthTypeName 获取认证类型名称
|
||||
func (s *datasourcePlatformService) getAuthTypeName(authType string) string {
|
||||
authTypeNames := map[string]string{
|
||||
"TOKEN": "Token认证",
|
||||
"API_KEY": "API Key认证",
|
||||
"OAUTH2": "OAuth2认证",
|
||||
"BASIC": "Basic认证",
|
||||
}
|
||||
if name, ok := authTypeNames[authType]; ok {
|
||||
return name
|
||||
}
|
||||
return authType
|
||||
}
|
||||
|
||||
// BatchUpdateStatus 批量更新平台状态
|
||||
func (s *datasourcePlatformService) BatchUpdateStatus(ctx context.Context, ids []int64, status string, updatedBy string) (err error) {
|
||||
if len(ids) == 0 {
|
||||
return errors.New("请选择要更新的平台")
|
||||
}
|
||||
|
||||
_, err = dao.DatasourcePlatform.BatchUpdateStatus(ctx, ids, status, updatedBy)
|
||||
return err
|
||||
}
|
||||
396
service/dict/api_field_mapping_config_service.go
Normal file
396
service/dict/api_field_mapping_config_service.go
Normal file
@@ -0,0 +1,396 @@
|
||||
package dict
|
||||
|
||||
import (
|
||||
consts "cid/consts/dict"
|
||||
"cid/dao/dict"
|
||||
dto "cid/model/dto/dict"
|
||||
entity "cid/model/entity/dict"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"gitea.com/red-future/common/beans"
|
||||
)
|
||||
|
||||
type fieldMappingConfigService struct{}
|
||||
|
||||
// FieldMappingConfig 字段映射配置服务
|
||||
var FieldMappingConfig = new(fieldMappingConfigService)
|
||||
|
||||
// Create 创建字段映射配置
|
||||
func (s *fieldMappingConfigService) Create(ctx context.Context, req *dto.CreateFieldMappingConfigReq) (res *dto.CreateFieldMappingConfigRes, err error) {
|
||||
// 验证必填字段
|
||||
if err = s.validateRequiredFields(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 检查重复配置
|
||||
exists, err := dict.FieldMappingConfig.CheckDuplicate(ctx, req.VendorName, req.ApiName, req.SourceField, req.TargetField, 0)
|
||||
if err != nil {
|
||||
return nil, errors.New("检查配置重复性失败")
|
||||
}
|
||||
if exists {
|
||||
return nil, errors.New("相同厂商、接口、源字段和目标字段的配置已存在")
|
||||
}
|
||||
|
||||
// 验证转换参数
|
||||
if err = s.validateTransformParams(req.TransformType, req.TransformParams); err != nil {
|
||||
return nil, fmt.Errorf("转换参数验证失败: %v", err)
|
||||
}
|
||||
|
||||
// 验证业务域
|
||||
if req.BusinessDomain != "" && !s.isValidBusinessDomain(req.BusinessDomain) {
|
||||
return nil, errors.New("无效的业务域")
|
||||
}
|
||||
|
||||
// 验证生效时间和失效时间
|
||||
if req.EffectiveDate != nil && req.ExpiryDate != nil && req.EffectiveDate.After(*req.ExpiryDate) {
|
||||
return nil, errors.New("生效时间不能晚于失效时间")
|
||||
}
|
||||
|
||||
// 插入数据库
|
||||
id, err := dict.FieldMappingConfig.Insert(ctx, req)
|
||||
if err != nil {
|
||||
return nil, errors.New("创建配置失败")
|
||||
}
|
||||
|
||||
res = &dto.CreateFieldMappingConfigRes{
|
||||
Id: id,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// List 获取字段映射配置列表
|
||||
func (s *fieldMappingConfigService) List(ctx context.Context, req *dto.ListFieldMappingConfigReq) (res *dto.ListFieldMappingConfigRes, err error) {
|
||||
configs, total, err := dict.FieldMappingConfig.List(ctx, req)
|
||||
if err != nil {
|
||||
return nil, errors.New("查询配置列表失败")
|
||||
}
|
||||
|
||||
// 组装响应数据
|
||||
list := make([]dto.FieldMappingConfigItem, 0, len(configs))
|
||||
for _, item := range configs {
|
||||
list = append(list, dto.FieldMappingConfigItem{
|
||||
Id: item.Id,
|
||||
ConfigName: item.ConfigName,
|
||||
VendorName: item.VendorName,
|
||||
ApiName: item.ApiName,
|
||||
ApiVersion: item.ApiVersion,
|
||||
SourceField: item.SourceField,
|
||||
TargetField: item.TargetField,
|
||||
TargetFieldType: item.TargetFieldType,
|
||||
TransformType: item.TransformType,
|
||||
TransformTypeName: s.getTransformTypeName(item.TransformType),
|
||||
IsActive: item.IsActive,
|
||||
Priority: item.Priority,
|
||||
BusinessDomain: item.BusinessDomain,
|
||||
BusinessDomainName: s.getBusinessDomainName(item.BusinessDomain),
|
||||
FieldGroup: item.FieldGroup,
|
||||
ConfigVersion: item.ConfigVersion,
|
||||
CreatedBy: item.CreatedBy,
|
||||
CreatedTime: item.CreatedTime,
|
||||
UpdatedBy: item.UpdatedBy,
|
||||
UpdatedTime: item.UpdatedTime,
|
||||
})
|
||||
}
|
||||
|
||||
res = &dto.ListFieldMappingConfigRes{
|
||||
List: list,
|
||||
Total: total,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetOne 获取单个字段映射配置
|
||||
func (s *fieldMappingConfigService) GetOne(ctx context.Context, req *dto.GetFieldMappingConfigReq) (res *dto.GetFieldMappingConfigRes, err error) {
|
||||
config, err := dict.FieldMappingConfig.GetOne(ctx, req)
|
||||
if err != nil {
|
||||
return nil, errors.New("获取配置详情失败")
|
||||
}
|
||||
if config == nil {
|
||||
return nil, errors.New("配置不存在")
|
||||
}
|
||||
|
||||
return &dto.GetFieldMappingConfigRes{
|
||||
FieldMappingConfig: config,
|
||||
TransformTypeName: s.getTransformTypeName(config.TransformType),
|
||||
BusinessDomainName: s.getBusinessDomainName(config.BusinessDomain),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Update 更新字段映射配置
|
||||
func (s *fieldMappingConfigService) Update(ctx context.Context, req *dto.UpdateFieldMappingConfigReq) (err error) {
|
||||
// 检查配置是否存在
|
||||
exist, err := dict.FieldMappingConfig.GetOne(ctx, &dto.GetFieldMappingConfigReq{Id: req.Id})
|
||||
if err != nil || exist == nil {
|
||||
return errors.New("配置不存在")
|
||||
}
|
||||
|
||||
// 如果修改了关键字段,检查重复性
|
||||
if (req.VendorName != "" && req.VendorName != exist.VendorName) ||
|
||||
(req.ApiName != "" && req.ApiName != exist.ApiName) ||
|
||||
(req.SourceField != "" && req.SourceField != exist.SourceField) ||
|
||||
(req.TargetField != "" && req.TargetField != exist.TargetField) {
|
||||
|
||||
vendorName := req.VendorName
|
||||
if vendorName == "" {
|
||||
vendorName = exist.VendorName
|
||||
}
|
||||
apiName := req.ApiName
|
||||
if apiName == "" {
|
||||
apiName = exist.ApiName
|
||||
}
|
||||
sourceField := req.SourceField
|
||||
if sourceField == "" {
|
||||
sourceField = exist.SourceField
|
||||
}
|
||||
targetField := req.TargetField
|
||||
if targetField == "" {
|
||||
targetField = exist.TargetField
|
||||
}
|
||||
|
||||
exists, err := dict.FieldMappingConfig.CheckDuplicate(ctx, vendorName, apiName, sourceField, targetField, req.Id)
|
||||
if err != nil {
|
||||
return errors.New("检查配置重复性失败")
|
||||
}
|
||||
if exists {
|
||||
return errors.New("相同厂商、接口、源字段和目标字段的配置已存在")
|
||||
}
|
||||
}
|
||||
|
||||
// 验证转换参数
|
||||
if req.TransformType != "" && req.TransformParams != nil {
|
||||
if err = s.validateTransformParams(req.TransformType, req.TransformParams); err != nil {
|
||||
return fmt.Errorf("转换参数验证失败: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// 验证生效时间和失效时间
|
||||
if req.EffectiveDate != nil && req.ExpiryDate != nil && req.EffectiveDate.After(*req.ExpiryDate) {
|
||||
return errors.New("生效时间不能晚于失效时间")
|
||||
}
|
||||
|
||||
// 更新数据库
|
||||
_, err = dict.FieldMappingConfig.Update(ctx, req)
|
||||
if err != nil {
|
||||
return errors.New("更新配置失败")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateStatus 更新字段映射配置状态
|
||||
func (s *fieldMappingConfigService) UpdateStatus(ctx context.Context, req *dto.UpdateFieldMappingConfigStatusReq) (err error) {
|
||||
_, err = dict.FieldMappingConfig.UpdateStatus(ctx, req.Id, req.IsActive)
|
||||
if err != nil {
|
||||
return errors.New("更新配置状态失败")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Delete 删除字段映射配置
|
||||
func (s *fieldMappingConfigService) Delete(ctx context.Context, req *dto.DeleteFieldMappingConfigReq) (err error) {
|
||||
_, err = dict.FieldMappingConfig.Delete(ctx, req)
|
||||
if err != nil {
|
||||
return errors.New("删除配置失败")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// QueryByVendorApi 根据厂商和接口查询字段映射
|
||||
func (s *fieldMappingConfigService) QueryByVendorApi(ctx context.Context, req *dto.QueryFieldMappingByVendorApiReq) (res *dto.QueryFieldMappingByVendorApiRes, err error) {
|
||||
configs, err := dict.FieldMappingConfig.GetByVendorAndApi(ctx, req.VendorName, req.ApiName, req.ApiVersion, req.IsActive)
|
||||
if err != nil {
|
||||
return nil, errors.New("查询字段映射配置失败")
|
||||
}
|
||||
|
||||
// 过滤掉已过期的配置
|
||||
var validConfigs []*entity.FieldMappingConfig
|
||||
now := time.Now()
|
||||
for _, config := range configs {
|
||||
if (config.EffectiveDate == nil || !config.EffectiveDate.After(now)) &&
|
||||
(config.ExpiryDate == nil || config.ExpiryDate.After(now)) {
|
||||
validConfigs = append(validConfigs, config)
|
||||
}
|
||||
}
|
||||
|
||||
res = &dto.QueryFieldMappingByVendorApiRes{
|
||||
List: validConfigs,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Validate 验证字段映射配置
|
||||
func (s *fieldMappingConfigService) Validate(ctx context.Context, req *dto.ValidateFieldMappingReq) (res *dto.ValidateFieldMappingRes, err error) {
|
||||
ctx = context.WithValue(ctx, "user", &beans.User{UserName: "admin"})
|
||||
res = &dto.ValidateFieldMappingRes{
|
||||
IsValid: false,
|
||||
}
|
||||
|
||||
// 验证基本配置
|
||||
if req.ConfigName == "" || req.VendorName == "" || req.ApiName == "" || req.SourceField == "" || req.TargetField == "" {
|
||||
res.Error = "配置名称、厂商名称、接口名称、源字段和目标字段不能为空"
|
||||
return
|
||||
}
|
||||
|
||||
// 检查重复配置
|
||||
exists, err := dict.FieldMappingConfig.CheckDuplicate(ctx, req.VendorName, req.ApiName, req.SourceField, req.TargetField, 0)
|
||||
if err != nil {
|
||||
res.Error = "检查配置重复性失败"
|
||||
return
|
||||
}
|
||||
if exists {
|
||||
res.Error = "相同厂商、接口、源字段和目标字段的配置已存在"
|
||||
return
|
||||
}
|
||||
|
||||
// 如果有测试值,尝试转换
|
||||
if req.TestValue != nil {
|
||||
// 这里可以实现具体的转换逻辑
|
||||
// 例如:根据转换类型和参数进行值转换
|
||||
res.TransformedValue = req.TestValue
|
||||
res.Warnings = []string{"转换逻辑需要根据具体业务实现"}
|
||||
}
|
||||
|
||||
res.IsValid = true
|
||||
return
|
||||
}
|
||||
|
||||
// validateRequiredFields 验证必填字段
|
||||
func (s *fieldMappingConfigService) validateRequiredFields(req *dto.CreateFieldMappingConfigReq) error {
|
||||
if req.ConfigName == "" {
|
||||
return errors.New("配置名称不能为空")
|
||||
}
|
||||
if req.VendorName == "" {
|
||||
return errors.New("厂商名称不能为空")
|
||||
}
|
||||
if req.ApiName == "" {
|
||||
return errors.New("接口名称不能为空")
|
||||
}
|
||||
if req.SourceField == "" {
|
||||
return errors.New("源字段不能为空")
|
||||
}
|
||||
if req.TargetField == "" {
|
||||
return errors.New("目标字段不能为空")
|
||||
}
|
||||
if req.TargetFieldType == "" {
|
||||
return errors.New("目标字段类型不能为空")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// validateRequiredFieldsForBatch 批量创建的字段验证
|
||||
func (s *fieldMappingConfigService) validateRequiredFieldsForBatch(config *dto.BatchFieldMappingConfigItem) error {
|
||||
if config.ConfigName == "" {
|
||||
return errors.New("配置名称不能为空")
|
||||
}
|
||||
if config.VendorName == "" {
|
||||
return errors.New("厂商名称不能为空")
|
||||
}
|
||||
if config.ApiName == "" {
|
||||
return errors.New("接口名称不能为空")
|
||||
}
|
||||
if config.SourceField == "" {
|
||||
return errors.New("源字段不能为空")
|
||||
}
|
||||
if config.TargetField == "" {
|
||||
return errors.New("目标字段不能为空")
|
||||
}
|
||||
if config.TargetFieldType == "" {
|
||||
return errors.New("目标字段类型不能为空")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// validateTransformParams 验证转换参数
|
||||
func (s *fieldMappingConfigService) validateTransformParams(transformType string, params map[string]interface{}) error {
|
||||
if params == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch transformType {
|
||||
case consts.TransformTypeFormatDate:
|
||||
if _, ok := params["source_format"]; !ok {
|
||||
return errors.New("日期格式化转换需要source_format参数")
|
||||
}
|
||||
if _, ok := params["target_format"]; !ok {
|
||||
return errors.New("日期格式化转换需要target_format参数")
|
||||
}
|
||||
case consts.TransformTypeMapValue:
|
||||
if len(params) == 0 {
|
||||
return errors.New("值映射转换需要映射规则参数")
|
||||
}
|
||||
case consts.TransformTypeConcat:
|
||||
if _, ok := params["fields"]; !ok {
|
||||
return errors.New("拼接转换需要fields参数")
|
||||
}
|
||||
case consts.TransformTypeRegex:
|
||||
if _, ok := params["pattern"]; !ok {
|
||||
return errors.New("正则提取转换需要pattern参数")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// isValidBusinessDomain 验证业务域是否有效
|
||||
func (s *fieldMappingConfigService) isValidBusinessDomain(domain string) bool {
|
||||
validDomains := []string{
|
||||
consts.BusinessDomainUser,
|
||||
consts.BusinessDomainOrder,
|
||||
consts.BusinessDomainProduct,
|
||||
consts.BusinessDomainPayment,
|
||||
}
|
||||
for _, valid := range validDomains {
|
||||
if domain == valid {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// getTransformTypeName 获取转换类型名称
|
||||
func (s *fieldMappingConfigService) getTransformTypeName(transformType string) string {
|
||||
typeNames := map[string]string{
|
||||
consts.TransformTypeDirect: "直接映射",
|
||||
consts.TransformTypeFormatDate: "日期格式化",
|
||||
consts.TransformTypeMapValue: "值映射",
|
||||
consts.TransformTypeConcat: "拼接",
|
||||
consts.TransformTypeCalc: "计算",
|
||||
consts.TransformTypeRegex: "正则提取",
|
||||
}
|
||||
if name, ok := typeNames[transformType]; ok {
|
||||
return name
|
||||
}
|
||||
return transformType
|
||||
}
|
||||
|
||||
// getBusinessDomainName 获取业务域名称
|
||||
func (s *fieldMappingConfigService) getBusinessDomainName(domain string) string {
|
||||
domainNames := map[string]string{
|
||||
consts.BusinessDomainUser: "用户",
|
||||
consts.BusinessDomainOrder: "订单",
|
||||
consts.BusinessDomainProduct: "商品",
|
||||
consts.BusinessDomainPayment: "支付",
|
||||
}
|
||||
if name, ok := domainNames[domain]; ok {
|
||||
return name
|
||||
}
|
||||
return domain
|
||||
}
|
||||
|
||||
// GetActiveConfigsByBusinessDomain 根据业务域获取启用的配置
|
||||
func (s *fieldMappingConfigService) GetActiveConfigsByBusinessDomain(ctx context.Context, businessDomain string) ([]entity.FieldMappingConfig, error) {
|
||||
return dict.FieldMappingConfig.GetActiveConfigsByBusinessDomain(ctx, businessDomain)
|
||||
}
|
||||
|
||||
// GetFieldGroupsByVendorApi 获取指定厂商接口的字段分组
|
||||
func (s *fieldMappingConfigService) GetFieldGroupsByVendorApi(ctx context.Context, vendorName, apiName string) ([]string, error) {
|
||||
return dict.FieldMappingConfig.GetFieldGroupsByVendorApi(ctx, vendorName, apiName)
|
||||
}
|
||||
|
||||
// CleanExpiredConfigs 清理过期配置
|
||||
func (s *fieldMappingConfigService) CleanExpiredConfigs(ctx context.Context) (int64, error) {
|
||||
return dict.FieldMappingConfig.DeleteExpiredConfigs(ctx)
|
||||
}
|
||||
183
service/dict/api_interface_service.go
Normal file
183
service/dict/api_interface_service.go
Normal file
@@ -0,0 +1,183 @@
|
||||
package dict
|
||||
|
||||
import (
|
||||
consts "cid/consts/api-feature"
|
||||
"cid/dao/dict"
|
||||
dto "cid/model/dto/dict"
|
||||
entity "cid/model/entity/dict"
|
||||
"context"
|
||||
"errors"
|
||||
)
|
||||
|
||||
type apiInterfaceService struct{}
|
||||
|
||||
// ApiInterface 接口服务
|
||||
var ApiInterface = new(apiInterfaceService)
|
||||
|
||||
// Create 创建接口
|
||||
func (s *apiInterfaceService) Create(ctx context.Context, req *dto.CreateApiInterfaceReq) (res *dto.CreateApiInterfaceRes, err error) {
|
||||
_, err = DatasourcePlatform.GetOne(ctx, &dto.GetDatasourcePlatformReq{Id: req.PlatformId})
|
||||
if err != nil {
|
||||
return nil, errors.New("平台不存在")
|
||||
}
|
||||
|
||||
// 检查接口编码在同一平台下是否重复
|
||||
interfaces, _, err := dict.ApiInterface.List(ctx, &dto.ListApiInterfaceReq{
|
||||
PlatformId: req.PlatformId,
|
||||
Code: req.Code,
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if len(interfaces) > 0 {
|
||||
return nil, errors.New("接口编码在该平台下已存在")
|
||||
}
|
||||
|
||||
// 插入数据库
|
||||
id, err := dict.ApiInterface.Insert(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
res = &dto.CreateApiInterfaceRes{
|
||||
Id: id,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// List 获取接口列表
|
||||
func (s *apiInterfaceService) List(ctx context.Context, req *dto.ListApiInterfaceReq) (res *dto.ListApiInterfaceRes, err error) {
|
||||
apiList, total, err := dict.ApiInterface.List(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
platformIds := make([]int64, 0)
|
||||
for _, item := range apiList {
|
||||
if item.PlatformId > 0 {
|
||||
platformIds = append(platformIds, item.PlatformId)
|
||||
}
|
||||
}
|
||||
|
||||
platformMap := make(map[int64]string)
|
||||
if len(platformIds) > 0 {
|
||||
res, err := DatasourcePlatform.List(ctx, &dto.ListDatasourcePlatformReq{})
|
||||
if err == nil && res != nil {
|
||||
for _, p := range res.List {
|
||||
platformMap[p.Id] = p.PlatformName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
list := make([]dto.ApiInterfaceItem, 0, len(apiList))
|
||||
for _, item := range apiList {
|
||||
platformName := ""
|
||||
if name, ok := platformMap[item.PlatformId]; ok {
|
||||
platformName = name
|
||||
}
|
||||
|
||||
list = append(list, dto.ApiInterfaceItem{
|
||||
Id: item.Id,
|
||||
PlatformId: item.PlatformId,
|
||||
PlatformName: platformName,
|
||||
Name: item.Name,
|
||||
Code: item.Code,
|
||||
Url: item.Url,
|
||||
Method: item.Method,
|
||||
Status: item.Status,
|
||||
StatusName: s.getStatusName(item.Status),
|
||||
CreatedAt: item.CreatedAt.Unix(),
|
||||
UpdatedAt: item.UpdatedAt.Unix(),
|
||||
})
|
||||
}
|
||||
|
||||
res = &dto.ListApiInterfaceRes{
|
||||
List: list,
|
||||
Total: total,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetOne 获取单个接口
|
||||
func (s *apiInterfaceService) GetOne(ctx context.Context, req *dto.GetApiInterfaceReq) (res *dto.GetApiInterfaceRes, err error) {
|
||||
apiInterface, err := dict.ApiInterface.GetOne(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var platformName string
|
||||
if apiInterface.PlatformId > 0 {
|
||||
platform, _ := DatasourcePlatform.GetOne(ctx, &dto.GetDatasourcePlatformReq{Id: apiInterface.PlatformId})
|
||||
if platform != nil {
|
||||
platformName = platform.PlatformName
|
||||
}
|
||||
}
|
||||
|
||||
return &dto.GetApiInterfaceRes{
|
||||
ApiInterface: apiInterface,
|
||||
PlatformName: platformName,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Update 更新接口
|
||||
func (s *apiInterfaceService) Update(ctx context.Context, req *dto.UpdateApiInterfaceReq) (err error) {
|
||||
exist, err := dict.ApiInterface.GetOne(ctx, &dto.GetApiInterfaceReq{Id: req.Id})
|
||||
if err != nil || exist == nil {
|
||||
return errors.New("接口不存在")
|
||||
}
|
||||
|
||||
if req.PlatformId > 0 && req.PlatformId != exist.PlatformId {
|
||||
_, err := DatasourcePlatform.GetOne(ctx, &dto.GetDatasourcePlatformReq{Id: req.PlatformId})
|
||||
if err != nil {
|
||||
return errors.New("平台不存在")
|
||||
}
|
||||
}
|
||||
|
||||
if req.Code != "" && req.Code != exist.Code {
|
||||
platformId := req.PlatformId
|
||||
if platformId == 0 {
|
||||
platformId = exist.PlatformId
|
||||
}
|
||||
interfaces, _, err := dict.ApiInterface.List(ctx, &dto.ListApiInterfaceReq{
|
||||
PlatformId: platformId,
|
||||
Code: req.Code,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(interfaces) > 0 {
|
||||
return errors.New("接口编码在该平台下已存在")
|
||||
}
|
||||
}
|
||||
|
||||
_, err = dict.ApiInterface.Update(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateStatus 更新接口状态
|
||||
func (s *apiInterfaceService) UpdateStatus(ctx context.Context, req *dto.UpdateApiInterfaceStatusReq) (err error) {
|
||||
_, err = dict.ApiInterface.UpdateStatus(ctx, req.Id, req.Status.String())
|
||||
return
|
||||
}
|
||||
|
||||
// Delete 删除接口
|
||||
func (s *apiInterfaceService) Delete(ctx context.Context, req *dto.DeleteApiInterfaceReq) (err error) {
|
||||
_, err = dict.ApiInterface.Delete(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// GetByIds 根据ID列表获取接口
|
||||
func (s *apiInterfaceService) GetByIds(ctx context.Context, ids []int64) (res []entity.ApiInterface, err error) {
|
||||
return dict.ApiInterface.GetByIds(ctx, ids)
|
||||
}
|
||||
|
||||
// getStatusName 获取状态名称
|
||||
func (s *apiInterfaceService) getStatusName(status consts.PlatformStatus) string {
|
||||
statusNames := map[consts.PlatformStatus]string{
|
||||
consts.PlatformStatusActive: "启用",
|
||||
consts.PlatformStatusInactive: "停用",
|
||||
}
|
||||
if name, ok := statusNames[status]; ok {
|
||||
return name
|
||||
}
|
||||
return string(status)
|
||||
}
|
||||
Reference in New Issue
Block a user