新原型的creative和图表接口
This commit is contained in:
parent
a3768b694e
commit
8e3dc9b325
@ -266,7 +266,7 @@ class BpsAdController
|
||||
|
||||
// 获取客户ID数组
|
||||
$accountIds = array_column($accounts, 'account_id');
|
||||
|
||||
// dump($accountIds);
|
||||
// 调用 Service 层查询广告组列表
|
||||
$result = $this->adsInsightService::getAdsetList(
|
||||
$platformType,
|
||||
@ -282,241 +282,96 @@ class BpsAdController
|
||||
return $this->successResponse($result, $request);
|
||||
}
|
||||
|
||||
|
||||
public function exportAdsToExcel(Request $request)
|
||||
public function listCreatives(Request $request)
|
||||
{
|
||||
$options = $request->all();
|
||||
$options = $request->all();
|
||||
$options['jwtClaims'] = $request->jwtClaims;
|
||||
|
||||
// 获取请求参数
|
||||
$keyword = $options['conditions']['keyword'] ?? ''; // 关键字搜索
|
||||
$startDate = $options['conditions']['startDate'] ?? null; // 开始日期
|
||||
$endDate = $options['conditions']['endDate'] ?? null; // 结束日期
|
||||
$dateRange = 'Last Week'; // 默认日期范围
|
||||
$page = $options['pageNo'] ?? 1; // 页码
|
||||
$pageSize = $options['pageSize'] ?? 1000; // 每页数量
|
||||
$keyword = $options['conditions']['keyword'] ?? ''; // 关键字搜索
|
||||
$platformType = $options['conditions']['platformType'] ?? 0; // 平台类型
|
||||
$startDate = $options['conditions']['startDate'] ?? null; // 开始日期
|
||||
$endDate = $options['conditions']['endDate'] ?? null; // 结束日期
|
||||
// $dateRange = 'Last Week'; // 默认日期范围
|
||||
|
||||
$customers = $this->googleOAuthService->getGoogleAdCustomers(['refresh_token' => $request->refresh_token]);
|
||||
$customerIds = array_column($customers, 'customer_id');
|
||||
// 调用 service 层导出数据
|
||||
return $this->googleAdsReportService::exportAdListToExcel($customerIds, $keyword, $dateRange, $startDate, $endDate);
|
||||
}
|
||||
// 根据 platformType 获取广告账户
|
||||
if ($platformType === 1) {
|
||||
$accounts = $this->bpsAdAccountService->getMetaAdAccounts(['refresh_token' => $request->refresh_token]);
|
||||
} elseif ($platformType === 2) {
|
||||
$accounts = $this->bpsAdAccountService->getGoogleAdAccounts(['refresh_token' => $request->refresh_token]);
|
||||
} elseif ($platformType === 3) {
|
||||
$accounts = $this->bpsAdAccountService->getTiktokAdAccounts(['refresh_token' => $request->refresh_token]);
|
||||
} else {
|
||||
// TODO: 匹配jwt的商户id还是登录用户id
|
||||
$accounts = $this->bpsAdAccountService->getAllAdAccounts(['uid' => $options['jwtClaims']['uid']]);
|
||||
}
|
||||
|
||||
public function exportCampaignsToExcel(Request $request)
|
||||
{
|
||||
$options = $request->all();
|
||||
// 获取请求参数
|
||||
$keyword = $options['conditions']['keyword'] ?? ''; // 关键字搜索
|
||||
$startDate = $options['conditions']['startDate'] ?? null; // 开始日期
|
||||
$endDate = $options['conditions']['endDate'] ?? null; // 结束日期
|
||||
$dateRange = 'Last Week'; // 默认日期范围
|
||||
if (empty($accounts)) {
|
||||
return $this->errorResponse(1, 'no data');
|
||||
}
|
||||
|
||||
$customers = $this->googleOAuthService->getGoogleAdCustomers(['refresh_token' => $request->refresh_token]);
|
||||
$customerIds = array_column($customers, 'customer_id');
|
||||
// dump($customerIds);
|
||||
// 调用 service 层导出数据
|
||||
return $this->googleAdsReportService->exportCampaignsToExcel($customerIds, $keyword, $dateRange, $startDate, $endDate);
|
||||
}
|
||||
|
||||
public function exportGroupsToExcel(Request $request)
|
||||
{
|
||||
$options = $request->all();
|
||||
// 获取请求参数
|
||||
$keyword = $options['conditions']['keyword'] ?? ''; // 关键字搜索
|
||||
$startDate = $options['conditions']['startDate'] ?? null; // 开始日期
|
||||
$endDate = $options['conditions']['endDate'] ?? null; // 结束日期
|
||||
$dateRange = 'Last Week'; // 默认日期范围
|
||||
|
||||
$customers = $this->googleOAuthService->getGoogleAdCustomers(['refresh_token' => $request->refresh_token]);
|
||||
$customerIds = array_column($customers, 'customer_id');
|
||||
|
||||
// 你可以进一步验证日期格式(可选)
|
||||
// if ($startDate && !strtotime($startDate)) {
|
||||
// return response()->json(['error' => 'Invalid start date format'], 400);
|
||||
// }
|
||||
// if ($endDate && !strtotime($endDate)) {
|
||||
// return response()->json(['error' => 'Invalid end date format'], 400);
|
||||
// }
|
||||
|
||||
// 调用 service 层导出数据
|
||||
return $this->googleAdsReportService->exportAdGroupsToExcel($customerIds, $keyword, $dateRange, $startDate, $endDate);
|
||||
}
|
||||
|
||||
public function listGroups(Request $request)
|
||||
{
|
||||
$options = $request->all();
|
||||
|
||||
// 获取请求参数
|
||||
$page = $options['pageNo'] ?? 1; // 页码
|
||||
$pageSize = $options['pageSize'] ?? 10; // 每页数量
|
||||
$keyword = $options['conditions']['keyword'] ?? ''; // 关键字搜索
|
||||
$startDate = $options['conditions']['startDate'] ?? null; // 开始日期
|
||||
$endDate = $options['conditions']['endDate'] ?? null; // 结束日期
|
||||
$dateRange = 'Last Week'; // 默认日期范围
|
||||
|
||||
$customers = $this->googleOAuthService->getGoogleAdCustomers(['refresh_token' => $request->refresh_token]);
|
||||
$customerIds = array_column($customers, 'customer_id');
|
||||
// 调用 Service 层查询
|
||||
$result = $this->googleAdsReportService::getAdGroupList(
|
||||
$customerIds, // 客户 ID 数组
|
||||
// 获取客户ID数组
|
||||
$accountIds = array_column($accounts, 'account_id');
|
||||
// dump($accountIds);
|
||||
// 调用 Service 层查询广告组列表
|
||||
$result = $this->adsInsightService->getCreativeInsightData(
|
||||
$platformType,
|
||||
$accountIds, // 客户 ID 数组
|
||||
$page, // 页码
|
||||
$pageSize, // 每页数量
|
||||
$keyword, // 关键字
|
||||
$dateRange,
|
||||
$startDate, // 开始日期
|
||||
$endDate
|
||||
$endDate // 结束日期
|
||||
);
|
||||
|
||||
// 返回结果
|
||||
return $this->successResponse($result, $request);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取广告系列的状态 备用
|
||||
*/
|
||||
// public function getCampaignStatus(int $campaignId): Response
|
||||
// {
|
||||
// try {
|
||||
// $status = $this->googleAdsCampaignService->getCampaignStatus($campaignId);
|
||||
// return $this->successResponse(['status' => $status]);
|
||||
// } catch (ValidateException $e) {
|
||||
// return $this->errorResponse(400, $e->getMessage());
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* 更新广告系列的状态
|
||||
*/
|
||||
public function updateCampaignStatus(Request $request): Response
|
||||
public function listCharts(Request $request)
|
||||
{
|
||||
$campaignStatus = [
|
||||
0, // UNSPECIFIED
|
||||
1, // UNKNOWN
|
||||
2, // ENABLED
|
||||
3, // PAUSED
|
||||
4, // REMOVED
|
||||
];
|
||||
$requestData = $request->all(); // 获取请求数据
|
||||
$requestData['refresh_token'] = $request->refresh_token;
|
||||
$requestData['login_customer_id'] = $request->login_customer_id;
|
||||
// dump($requestData);
|
||||
$options = $request->all();
|
||||
$options['jwtClaims'] = $request->jwtClaims;
|
||||
|
||||
$status = $requestData['status'];
|
||||
if (!in_array($status, $campaignStatus)) {
|
||||
return $this->errorResponse(101, 'status参数错误');
|
||||
// 获取请求参数
|
||||
$cycle = $options['conditions']['cycle'] ?? 3; // 页码
|
||||
$platformType = $options['conditions']['platformType'] ?? 0; // 平台类型
|
||||
$startDate = $options['conditions']['startDate'] ?? null; // 开始日期
|
||||
$endDate = $options['conditions']['endDate'] ?? null; // 结束日期
|
||||
// $dateRange = 'Last Week'; // 默认日期范围
|
||||
|
||||
// 根据 platformType 获取广告账户
|
||||
if ($platformType === 1) {
|
||||
$accounts = $this->bpsAdAccountService->getMetaAdAccounts(['refresh_token' => $request->refresh_token]);
|
||||
} elseif ($platformType === 2) {
|
||||
$accounts = $this->bpsAdAccountService->getGoogleAdAccounts(['refresh_token' => $request->refresh_token]);
|
||||
} elseif ($platformType === 3) {
|
||||
$accounts = $this->bpsAdAccountService->getTiktokAdAccounts(['refresh_token' => $request->refresh_token]);
|
||||
} else {
|
||||
// TODO: 匹配jwt的商户id还是登录用户id
|
||||
$accounts = $this->bpsAdAccountService->getAllAdAccounts(['uid' => $options['jwtClaims']['uid']]);
|
||||
}
|
||||
// try {
|
||||
$reslut = $this->googleAdsCampaignService->updateCampaignStatus($requestData);
|
||||
if (!$reslut) {
|
||||
return $this->errorResponse(101, 'Status update failed');
|
||||
|
||||
if (empty($accounts)) {
|
||||
return $this->errorResponse(1, 'no data');
|
||||
}
|
||||
return $this->successResponse(['message' => 'Status updated successfully'], $request);
|
||||
// } catch (ValidateException $e) {
|
||||
// return $this->errorResponse(400, $e->getMessage());
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断广告系列是否启用
|
||||
*/
|
||||
// public function isEnabled(int $campaignId): Json
|
||||
// {
|
||||
// try {
|
||||
// $isEnabled = $this->campaignService->isCampaignEnabled($campaignId);
|
||||
// return json(['enabled' => $isEnabled], 200);
|
||||
// } catch (ValidateException $e) {
|
||||
// return json(['error' => $e->getMessage()], 400);
|
||||
// }
|
||||
// }
|
||||
// 获取客户ID数组
|
||||
$accountIds = array_column($accounts, 'account_id');
|
||||
// dump($accountIds);
|
||||
// 调用 Service 层查询广告组列表
|
||||
$result = $this->adsInsightService->getAdCycleInsight(
|
||||
$platformType,
|
||||
$accountIds, // 客户 ID 数组
|
||||
$cycle, // 页码
|
||||
$startDate, // 开始日期
|
||||
$endDate // 结束日期
|
||||
);
|
||||
|
||||
/**
|
||||
* 判断广告系列是否暂停
|
||||
*/
|
||||
// public function isPaused(int $campaignId): Json
|
||||
// {
|
||||
// try {
|
||||
// $isPaused = $this->campaignService->isCampaignPaused($campaignId);
|
||||
// return json(['paused' => $isPaused], 200);
|
||||
// } catch (ValidateException $e) {
|
||||
// return json(['error' => $e->getMessage()], 400);
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* 判断广告系列是否停止
|
||||
*/
|
||||
// public function isStopped(int $campaignId): Json
|
||||
// {
|
||||
// try {
|
||||
// $isStopped = $this->campaignService->isCampaignStopped($campaignId);
|
||||
// return json(['stopped' => $isStopped], 200);
|
||||
// } catch (ValidateException $e) {
|
||||
// return json(['error' => $e->getMessage()], 400);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
|
||||
/**
|
||||
* 更新广告组的状态
|
||||
*/
|
||||
public function updateGroupStatus(Request $request): Response
|
||||
{
|
||||
$adGroupStatus = [
|
||||
0, // UNSPECIFIED
|
||||
1, // UNKNOWN
|
||||
2, // ENABLED
|
||||
3, // PAUSED
|
||||
4 // REMOVED
|
||||
];
|
||||
|
||||
$requestData = $request->all(); // 获取请求数据
|
||||
$requestData['refresh_token'] = $request->refresh_token;
|
||||
$requestData['login_customer_id'] = $request->login_customer_id;
|
||||
// dump($requestData);
|
||||
|
||||
$status = $requestData['status'];
|
||||
// $options['bid_micro_amount'] = $options['amount'] * 1000000 < 0 ? 0 : $options['amount'] * 1000000;
|
||||
if (!in_array($status, $adGroupStatus)) {
|
||||
return $this->errorResponse(101, 'status参数错误');
|
||||
}
|
||||
// try {
|
||||
$result = $this->googleAdsGroupService->updateGroupStatus($requestData);
|
||||
if (!$result) {
|
||||
return $this->errorResponse(101, 'Status update failed');
|
||||
}
|
||||
return $this->successResponse(['message' => 'Status updated successfully'], $request);
|
||||
// } catch (ValidateException $e) {
|
||||
// return $this->errorResponse(400, $e->getMessage());
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新广告的状态
|
||||
*/
|
||||
public function updateAdStatus(Request $request): Response
|
||||
{
|
||||
$adStatus = [
|
||||
0, // UNSPECIFIED
|
||||
1, // UNKNOWN
|
||||
2, // ENABLED
|
||||
3, // PAUSED
|
||||
4 // REMOVED
|
||||
];
|
||||
|
||||
$requestData = $request->all(); // 获取请求数据
|
||||
$requestData['refresh_token'] = $request->refresh_token;
|
||||
$requestData['login_customer_id'] = $request->login_customer_id;
|
||||
// dump($requestData);
|
||||
|
||||
$status = $requestData['status'];
|
||||
if (!in_array($status, $adStatus)) {
|
||||
return $this->errorResponse(101, 'status参数错误');
|
||||
}
|
||||
// try {
|
||||
$result = $this->googleAdsAdService->updateAdStatus($requestData);
|
||||
if (!$result) {
|
||||
return $this->errorResponse(101, 'Status update failed');
|
||||
}
|
||||
return $this->successResponse(['message' => 'Status updated successfully'], $request);
|
||||
// } catch (ValidateException $e) {
|
||||
// return $this->errorResponse(400, $e->getMessage());
|
||||
// }
|
||||
// 返回结果
|
||||
return $this->successResponse($result, $request);
|
||||
}
|
||||
|
||||
|
||||
|
@ -248,6 +248,8 @@ class GoogleAdsController
|
||||
*/
|
||||
public function getCampaigns($options): Response
|
||||
{
|
||||
$options['login_customer_id'] = 1401879025;
|
||||
$options['refresh_token'] = '1//0en4AWGamrTnOCgYIARAAGA4SNwF-L9IrMOw2DkHF2y3DL2kDiEmOUzk5KTsR1f1iU_axBNi-LgxfT_76JHK4AY1KChZWfyNc0Qs';
|
||||
$resourceName = $this->googleAdsCampaignService->runListCampaigns($options['customer_id'], $options);
|
||||
return $this->successResponse(['campaigns_list' => $resourceName]);
|
||||
}
|
||||
@ -267,6 +269,9 @@ class GoogleAdsController
|
||||
*/
|
||||
public function getAds($options): Response
|
||||
{
|
||||
$options['login_customer_id'] = 1401879025;
|
||||
$options['refresh_token'] = '1//0en4AWGamrTnOCgYIARAAGA4SNwF-L9IrMOw2DkHF2y3DL2kDiEmOUzk5KTsR1f1iU_axBNi-LgxfT_76JHK4AY1KChZWfyNc0Qs';
|
||||
|
||||
$resourceName = $this->googleAdsAdService->runListAds($options['customer_id'],$options);
|
||||
return $this->successResponse(['groups_list' => $resourceName]);
|
||||
}
|
||||
@ -312,9 +317,11 @@ class GoogleAdsController
|
||||
*/
|
||||
public function getDateDatas($options): Response
|
||||
{
|
||||
$options['login_customer_id'] = 1509096882;
|
||||
$options['refresh_token'] = '1//0eOTBBKbP-sPACgYIARAAGA4SNwF-L9Irg1hApAtVpZfvSCKX_pSSV2CJ7Fye3m1p3Nw12VbCjJ2Ey2D02dVy5iDhCET79TfWY0s';
|
||||
$resourceName = $this->googleAdsCampaignService->runListDateDatas($options['customer_id'],$options, '2025-01-04');
|
||||
$todayStart = date('Y-m-d', strtotime('0 day'));
|
||||
$options['login_customer_id'] = 1401879025;
|
||||
$options['refresh_token'] = '1//0en4AWGamrTnOCgYIARAAGA4SNwF-L9IrMOw2DkHF2y3DL2kDiEmOUzk5KTsR1f1iU_axBNi-LgxfT_76JHK4AY1KChZWfyNc0Qs';
|
||||
// dump($todayStart);
|
||||
$resourceName = $this->googleAdsCampaignService->runListDateDatas($options['customer_id'],$options, '2025-01-09');
|
||||
return $this->successResponse(['date_datas_list' => $resourceName]);
|
||||
}
|
||||
|
||||
|
50
app/model/BpsAdCreative.php
Normal file
50
app/model/BpsAdCreative.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use think\Model;
|
||||
|
||||
class BpsAdCreative extends Model
|
||||
{
|
||||
// 设置当前模型对应的完整数据表名称
|
||||
protected $table = 'bps.bps_ads_creative';
|
||||
|
||||
// 设置主键
|
||||
// protected $pk = 'creative_id';
|
||||
|
||||
// 设置自动时间戳
|
||||
protected $autoWriteTimestamp = true;
|
||||
|
||||
// 定义时间戳字段
|
||||
protected $createTime = 'created_at';
|
||||
protected $updateTime = 'updated_at';
|
||||
|
||||
// 设置字段类型和默认值
|
||||
protected $casts = [
|
||||
'platform' => 'int',
|
||||
'account_id' => 'string',
|
||||
'customer_id' => 'string',
|
||||
'creative_id' => 'string',
|
||||
'name' => 'string',
|
||||
'title' => 'string',
|
||||
'thumbnail_url' => 'string',
|
||||
'url' => 'string',
|
||||
'type' => 'int',
|
||||
'object_type' => 'string',
|
||||
'status' => 'int',
|
||||
'created_at' => 'timestamp',
|
||||
'updated_at' => 'timestamp',
|
||||
];
|
||||
|
||||
// 默认值设置
|
||||
protected $defaults = [
|
||||
'name' => '',
|
||||
'title' => '',
|
||||
'thumbnail_url' => '',
|
||||
'url' => '',
|
||||
'type' => 1, // 默认为图片
|
||||
'object_type' => '',
|
||||
'status' => 2, // 默认为启用
|
||||
];
|
||||
|
||||
}
|
94
app/model/BpsAdCreativeInsight.php
Normal file
94
app/model/BpsAdCreativeInsight.php
Normal file
@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
namespace app\model;
|
||||
|
||||
use think\Model;
|
||||
|
||||
class BpsAdCreativeInsight extends Model
|
||||
{
|
||||
// 设置当前模型对应的完整数据表名称
|
||||
protected $table = 'bps.bps_ads_creative_insights';
|
||||
|
||||
// 设置复合主键
|
||||
protected $pk = ['id'];
|
||||
|
||||
// 设置自动时间戳
|
||||
protected $autoWriteTimestamp = true;
|
||||
|
||||
// 定义时间戳字段
|
||||
protected $createTime = 'create_at';
|
||||
protected $updateTime = 'update_at';
|
||||
|
||||
// 设置字段类型和默认值
|
||||
protected $casts = [
|
||||
'platform' => 'int',
|
||||
'creative_id' => 'int',
|
||||
'account_id' => 'int',
|
||||
'clicks' => 'int',
|
||||
'spend' => 'int',
|
||||
'purchases_value' => 'int',
|
||||
'revenue' => 'int',
|
||||
'impressions' => 'int',
|
||||
'date' => 'date',
|
||||
];
|
||||
|
||||
// 默认值设置
|
||||
protected $defaults = [
|
||||
'clicks' => 0,
|
||||
'spend' => 0,
|
||||
'purchases_value' => 0,
|
||||
'revenue ' => 0,
|
||||
'impressions' => 0,
|
||||
'ad_name' => '',
|
||||
];
|
||||
|
||||
// 检查唯一键
|
||||
// protected function checkUniqueKey()
|
||||
// {
|
||||
// $exists = $this->where('ad_id', $this->ad_id)
|
||||
// ->where('date', $this->date)
|
||||
// ->where('platform', $this->platform)
|
||||
// ->find();
|
||||
//
|
||||
// if ($exists && $exists->id != $this->id) {
|
||||
// throw new \Exception('数据已存在,ad_id、date 和 platform 必须唯一');
|
||||
// }
|
||||
// }
|
||||
|
||||
// 在保存数据前调用
|
||||
// protected static function onBeforeWrite($model)
|
||||
// {
|
||||
// $model->checkUniqueKey();
|
||||
// }
|
||||
|
||||
|
||||
// 关联 Campaign 模型(报告数据属于广告活动)
|
||||
// public function campaign()
|
||||
// {
|
||||
// return $this->belongsTo(BpsAdCampaign::class, 'campaign_id', 'campaign_id');
|
||||
// }
|
||||
|
||||
// 关联 AdGroup 模型(报告数据属于广告组)
|
||||
// public function adSet()
|
||||
// {
|
||||
// return $this->belongsTo(BpsAdSet::class, 'ad_set_id', 'ad_set_id');
|
||||
// }
|
||||
|
||||
// 关联 Ad 模型(报告数据属于广告)
|
||||
// public function ad()
|
||||
// {
|
||||
// return $this->belongsTo(BpsAdAd::class, 'ad_id', 'ad_id');
|
||||
// }
|
||||
|
||||
// 关联 Customer 模型(报告数据与客户相关)
|
||||
// public function customer()
|
||||
// {
|
||||
// return $this->belongsTo(GoogleAdsCustomer::class, 'account_id', 'account_id');
|
||||
// }
|
||||
|
||||
// 关联 Budget 模型(报告数据与预算相关)
|
||||
// public function budget()
|
||||
// {
|
||||
// return $this->belongsTo(CampaignBudget::class, 'budget_id', 'budget_id');
|
||||
// }
|
||||
}
|
@ -3,6 +3,8 @@
|
||||
namespace app\service;
|
||||
|
||||
use app\model\Ad;
|
||||
use app\model\BpsAdCreativeInsight;
|
||||
use app\model\BpsAdInsight;
|
||||
use app\model\DayData;
|
||||
use app\model\Campaign;
|
||||
use app\model\BpsAdCampaign;
|
||||
@ -641,19 +643,8 @@ class AdsInsightService
|
||||
* @param int $pageSize 每页数量
|
||||
* @return array
|
||||
*/
|
||||
public function getAssetConversionData($customerIds, $page, $pageSize, $keyword, $dateRange, $startDate = null, $endDate = null)
|
||||
public function getCreativeInsightData11111($platformType, $customerIds, $page, $pageSize, $keyword, $startDate = null, $endDate = null)
|
||||
{
|
||||
|
||||
$isSameMonth = true; // 判断是否跨月
|
||||
$currentMonth = date('Y-m'); //一个月内的统计需要确定是什么月份。
|
||||
if ($startDate && $endDate) {
|
||||
// 比较日期的年月是否相同,若不同则为跨月
|
||||
$isSameMonth = date('Y-m', strtotime($startDate)) === date('Y-m', strtotime($endDate));
|
||||
if ($isSameMonth) {
|
||||
$currentMonth = date('Y-m', strtotime($startDate));
|
||||
}
|
||||
}
|
||||
|
||||
// 1. 获取符合条件的 ad_id 列表,并且筛选 AssetRelation 的 date 字段
|
||||
$adIdsQuery = AssetRelation::alias('r')
|
||||
->leftJoin('bps.bps_google_ads_asset a', 'r.asset_id = a.asset_id') // 关联资产表
|
||||
@ -669,7 +660,6 @@ class AdsInsightService
|
||||
} else {
|
||||
return [
|
||||
'data' => [],
|
||||
'chat_1_data' => [], // 返回按月汇总的 chat_data
|
||||
'total' => 0,
|
||||
'statistics' => [],
|
||||
'pagination' => [
|
||||
@ -686,281 +676,263 @@ class AdsInsightService
|
||||
// 日期范围处理,筛选 AssetRelation 的 date 字段
|
||||
if ($startDate && $endDate) {
|
||||
$adIdsQuery->whereBetween('r.date', [$startDate, $endDate]);
|
||||
} else {
|
||||
switch ($dateRange) {
|
||||
case 'Today':
|
||||
$adIdsQuery->where('r.date', '=', date('Y-m-d'));
|
||||
$currentMonth = date('Y-m');
|
||||
$isSameMonth = true;
|
||||
break;
|
||||
case 'Yesterday':
|
||||
$adIdsQuery->where('r.date', '=', date('Y-m-d', strtotime('-1 day')));
|
||||
$currentMonth = date('Y-m', strtotime('-1 day'));
|
||||
$isSameMonth = true;
|
||||
break;
|
||||
case 'Last Week':
|
||||
$adIdsQuery->where('r.date', '>=', date('Y-m-d', strtotime('-1 week')));
|
||||
// 比较日期的年月是否相同,若不同则为跨月
|
||||
$isSameMonth = date('Y-m', strtotime('-1 week')) === date('Y-m');
|
||||
break;
|
||||
case 'Last Month':
|
||||
$adIdsQuery->where('r.date', '>=', date('Y-m-d', strtotime('-1 month')));
|
||||
$isSameMonth = false;
|
||||
break;
|
||||
case 'Last Year':
|
||||
$adIdsQuery->where('r.date', '>=', date('Y-m-d', strtotime('-1 year')));
|
||||
$isSameMonth = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 获取唯一的 ad_id 列表
|
||||
$adIds = $adIdsQuery->distinct(true)->column('r.ad_id');
|
||||
// dump($adIds);return($adIds);
|
||||
|
||||
// 2. 根据 ad_id 和日期范围去查询 DayData 表,按 ad_id 和日期聚合统计
|
||||
// 2. 根据 ad_id 和日期范围去查询 DayData 表,按 ad_id 聚合统计
|
||||
$dayDataQuery = DayData::alias('d')
|
||||
// ->leftJoin('bps.bps_google_ads_campaign c', 'd.campaign_id = c.campaign_id') // 关联广告系列表(如果有)
|
||||
// ->leftJoin('bps.bps_google_ads_ad_group ag', 'd.ad_group_id = ag.ad_group_id') // 关联广告组表(如果有)
|
||||
->whereIn('d.ad_id', $adIds) // 使用 ad_id 过滤
|
||||
->where(function ($query) use ($startDate, $endDate, $dateRange) {
|
||||
->where(function ($query) use ($startDate, $endDate) {
|
||||
// 日期范围的筛选
|
||||
if ($startDate && $endDate) {
|
||||
$query->whereBetween('d.date', [$startDate, $endDate]);
|
||||
} else {
|
||||
switch ($dateRange) {
|
||||
case 'Today':
|
||||
$query->where('d.date', '=', date('Y-m-d'));
|
||||
break;
|
||||
case 'Yesterday':
|
||||
$query->where('d.date', '=', date('Y-m-d', strtotime('-1 day')));
|
||||
break;
|
||||
case 'Last Week':
|
||||
$query->where('d.date', '>=', date('Y-m-d', strtotime('-1 week')));
|
||||
break;
|
||||
case 'Last Month':
|
||||
$query->where('d.date', '>=', date('Y-m-d', strtotime('-1 month')));
|
||||
break;
|
||||
case 'Last Year':
|
||||
$query->where('d.date', '>=', date('Y-m-d', strtotime('-1 year')));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 如果跨月,按月聚合;如果不跨月,按 ad_id 聚合
|
||||
if (!$isSameMonth) {
|
||||
$dayDataQuery->group("d.month,d.ad_id,d.ad_name, d.ad_resource_name, d.ad_group_id, d.campaign_id, d.customer_id"); // 按月聚合
|
||||
$dayDataQuery->field([
|
||||
'd.ad_id',
|
||||
'd.month',
|
||||
// ThinkDb::raw("TO_CHAR(d.date, 'YYYY-MM') AS month"), // 格式化为 YYYY-MM 格式
|
||||
ThinkDb::raw('SUM(d.cost_micros) / 1000000 AS total_spend'),
|
||||
ThinkDb::raw('SUM(d.conversions_value) AS total_conversions_value'),
|
||||
ThinkDb::raw('SUM(d.conversions) AS total_conversions'),
|
||||
ThinkDb::raw('SUM(d.impressions) AS total_impressions'),
|
||||
ThinkDb::raw('SUM(d.clicks) AS total_clicks')
|
||||
]);
|
||||
} else {
|
||||
$dayDataQuery->group('d.ad_id,d.ad_name, d.ad_resource_name, d.ad_group_id, d.campaign_id, d.customer_id'); // 按 ad_id 聚合
|
||||
$dayDataQuery->field([
|
||||
'd.ad_id',
|
||||
ThinkDb::raw('SUM(d.cost_micros) / 1000000 AS total_spend'),
|
||||
ThinkDb::raw('SUM(d.conversions_value) AS total_conversions_value'),
|
||||
ThinkDb::raw('SUM(d.conversions) AS total_conversions'),
|
||||
ThinkDb::raw('SUM(d.impressions) AS total_impressions'),
|
||||
ThinkDb::raw('SUM(d.clicks) AS total_clicks')
|
||||
]);
|
||||
}
|
||||
|
||||
// 获取聚合数据,不需要再传递字段给 select()
|
||||
$dayDataQuery->group('d.ad_id,d.ad_name, d.ad_resource_name, d.ad_group_id, d.campaign_id, d.customer_id'); // 按 ad_id 聚合
|
||||
$dayDataQuery->field([
|
||||
'd.ad_id',
|
||||
ThinkDb::raw('SUM(d.cost_micros) / 1000000 AS total_spend'),
|
||||
ThinkDb::raw('SUM(d.conversions_value) AS total_conversions_value'),
|
||||
ThinkDb::raw('SUM(d.conversions) AS total_conversions'),
|
||||
ThinkDb::raw('SUM(d.impressions) AS total_impressions'),
|
||||
ThinkDb::raw('SUM(d.clicks) AS total_clicks')
|
||||
]);
|
||||
|
||||
// 获取聚合数据
|
||||
$aggregatedData = $dayDataQuery->select();
|
||||
// dump($aggregatedData);return($aggregatedData);
|
||||
|
||||
// 3. 获取与 ad_id 关联的 asset_id 以及相关数据
|
||||
$assetRelationsQuery = AssetRelation::whereIn('ad_id', $adIds)
|
||||
->whereBetween('date', [$startDate, $endDate]) // 加上 AssetRelation 的 date 过滤
|
||||
->field(['asset_id', 'ad_id'])->select();
|
||||
// dump($assetRelationsQuery);return($assetRelationsQuery);
|
||||
// 4. 汇总每个 asset_id 下的所有 ad_id 的聚合数据
|
||||
|
||||
// 4. 汇总每个 asset_id 下的所有 ad_id 的聚合数据
|
||||
$assetSummaryData = [];
|
||||
$statisticsData = $this->initializeStatistics(); // 初始化统计数据
|
||||
|
||||
foreach ($assetRelationsQuery as $assetRelation) {
|
||||
// 从聚合数据中找到当前 ad_id 的相关数据
|
||||
// $adStats = $aggregatedData->where('ad_id', $assetRelation->ad_id)->first();
|
||||
// 获取该 ad_id 的所有聚合数据(可能有多条记录)
|
||||
$adStatsCollection = $aggregatedData->where('ad_id', $assetRelation->ad_id);
|
||||
// dump($adStatsCollection);return($adStatsCollection);
|
||||
|
||||
if (!$adStatsCollection->isEmpty()) {
|
||||
// 如果该 ad_id 有对应的聚合数据,初始化资产汇总数据
|
||||
if (!isset($assetSummaryData[$assetRelation->asset_id])) {
|
||||
|
||||
|
||||
$assetSummaryData[$assetRelation->asset_id] = [
|
||||
'asset_id' => $assetRelation->asset_id,
|
||||
'asset_name' => '-', // 获取 asset_name
|
||||
'asset_type' => 0, // 获取 asset_type
|
||||
'asset_url' => '-', // 获取 asset_url
|
||||
'total_spend' => 0,
|
||||
'creative_id' => $assetRelation->asset_id,
|
||||
'creative' => '-',
|
||||
'creative_type' => 0,
|
||||
'creative_url' => '-',
|
||||
'spend' => 0,
|
||||
'purchase_value' => '-',
|
||||
'roas' => 0,
|
||||
'cpa' => '-',
|
||||
'cpc_link_click' => '-',
|
||||
'cpm' => '-',
|
||||
'cpc_all' => '-',
|
||||
'aov' => '-',
|
||||
'click_to_atc_ratio' => '-',
|
||||
'atc_to_purchase_ratio' => '-',
|
||||
'purchases' => '-',
|
||||
'first_frame_retention' => '-',
|
||||
'thumbstop' => '-',
|
||||
'ctr_outbound' => '-',
|
||||
'click_to_purchase' => '-',
|
||||
'ctr_all' => '-',
|
||||
'video_plays_25_rate' => '-',
|
||||
'video_plays_50_rate' => '-',
|
||||
'video_plays_75_rate' => '-',
|
||||
'video_plays_100_rate' => '-',
|
||||
'hold_rate' => '-',
|
||||
'total_conversions_value' => 0,
|
||||
'total_conversions' => 0,
|
||||
'total_impressions' => 0,
|
||||
'ad_count' => 0,
|
||||
'monthly_data' => [], // 按月存储数据
|
||||
'ad_count' => 0
|
||||
];
|
||||
}
|
||||
|
||||
// 遍历该 ad_id 所有的统计数据
|
||||
// 更新每个广告素材的统计数据
|
||||
foreach ($adStatsCollection as $adStats) {
|
||||
// 获取当前月份
|
||||
if ($isSameMonth) {
|
||||
$month = $currentMonth; // 格式化为 YYYY-MM
|
||||
} else {
|
||||
$month = $adStats->month; // 格式化日期为 'YYYY-MM'
|
||||
}
|
||||
// 获取 asset 相关信息,通过模型查询 Asset
|
||||
$asset = Asset::find($assetRelation->asset_id); // 根据 asset_id 查找对应的 Asset 数据
|
||||
// 累加该 ad_id 的统计数据到对应的 asset_id 汇总
|
||||
$assetSummaryData[$assetRelation->asset_id]['asset_name'] = $asset->asset_name;
|
||||
$assetSummaryData[$assetRelation->asset_id]['asset_type'] = $asset->asset_type;
|
||||
$assetSummaryData[$assetRelation->asset_id]['asset_url'] = $asset->asset_url;
|
||||
$assetSummaryData[$assetRelation->asset_id]['total_spend'] += $adStats->total_spend;
|
||||
$assetSummaryData[$assetRelation->asset_id]['spend'] += $adStats->total_spend;
|
||||
$assetSummaryData[$assetRelation->asset_id]['total_conversions_value'] += $adStats->total_conversions_value;
|
||||
$assetSummaryData[$assetRelation->asset_id]['total_conversions'] += $adStats->total_conversions;
|
||||
$assetSummaryData[$assetRelation->asset_id]['total_impressions'] += $adStats->total_impressions;
|
||||
$assetSummaryData[$assetRelation->asset_id]['ad'][] = $adStats->ad_id; // 存储 ad_id下一步统计数量
|
||||
|
||||
// 按月分开存储每个月的 spend 和 ROAS
|
||||
if (!isset($assetSummaryData[$assetRelation->asset_id]['monthly_data'][$month])) {
|
||||
$assetSummaryData[$assetRelation->asset_id]['monthly_data'][$month] = [
|
||||
'month' => $month,
|
||||
'spend' => 0,
|
||||
'conversions_value' => 0,
|
||||
];
|
||||
}
|
||||
|
||||
// 累加每个月的数据
|
||||
$assetSummaryData[$assetRelation->asset_id]['monthly_data'][$month]['spend'] += $adStats->total_spend;
|
||||
$assetSummaryData[$assetRelation->asset_id]['monthly_data'][$month]['conversions_value'] += $adStats->total_conversions_value; // 避免除以零
|
||||
}
|
||||
}
|
||||
}
|
||||
//return $assetSummaryData;
|
||||
// 5. 格式化输出数据
|
||||
// 生成最终输出的数据
|
||||
$resultData = [];
|
||||
$chat_data = [];
|
||||
$statistics = $this->initializeStatistics(); // Initialize statistics before processing
|
||||
|
||||
foreach ($assetSummaryData as $assetId => $data) {
|
||||
// 计算 ROAS
|
||||
$roas = $data['total_spend'] ? ($data['total_conversions_value'] / $data['total_spend']) : 0;
|
||||
|
||||
// 合并月度数据到总数据
|
||||
$resultData[] = [
|
||||
'creative_id' => $assetId,
|
||||
'creative' => $data['asset_name'],
|
||||
'creative_type' => $data['asset_type'],
|
||||
'creative_url' => $data['asset_url'],
|
||||
'spend' => '$' . number_format($data['total_spend'], 2),
|
||||
'purchase_value' => '-',
|
||||
'roas' => number_format($roas, 2) . 'X',
|
||||
'cpa' => '-',
|
||||
'cpc_link_click' => '-',
|
||||
'cpm' => '-',
|
||||
'cpc_all' => '-',
|
||||
'aov' => '-',
|
||||
'click_to_atc_ratio' => '-',
|
||||
'atc_to_purchase_ratio' => '-',
|
||||
'purchases' => '-',
|
||||
'first_frame_retention' => '-',
|
||||
'thumbstop' => '-',
|
||||
'ctr_outbound' => '-',
|
||||
'click_to_purchase' => '-',
|
||||
'ctr_all' => '-',
|
||||
'video_plays_25_rate' => '-',
|
||||
'video_plays_50_rate' => '-',
|
||||
'video_plays_75_rate' => '-',
|
||||
'video_plays_100_rate' => '-',
|
||||
'hold_rate' => '-',
|
||||
'total_conversions_value' => '$' . number_format($data['total_conversions_value'], 2),
|
||||
'total_conversions' => $data['total_conversions'],
|
||||
'total_impressions' => $data['total_impressions'],
|
||||
'ad_count' => count($data['ad']),
|
||||
|
||||
// 'monthly_data' => $data['monthly_data'], // 合并月度数据
|
||||
];
|
||||
|
||||
// 计算每个月的汇总数据,用于 chat_data
|
||||
foreach ($data['monthly_data'] as $month => $monthlyData) {
|
||||
// 如果 chat_data 中已有该月的数据,则累加
|
||||
if (!isset($chat_data[$month])) {
|
||||
$chat_data[$month] = [
|
||||
'month' => $month,
|
||||
'total_spend' => 0,
|
||||
'total_conversions_value' => 0,
|
||||
'roas' => 0,
|
||||
];
|
||||
// 汇总 statisticsData
|
||||
$statisticsData['spend'] += $adStats->total_spend;
|
||||
$statisticsData['conversions_value'] += $adStats->total_conversions_value;
|
||||
$statisticsData['total_conversions'] += $adStats->total_conversions;
|
||||
$statisticsData['total_impressions'] += $adStats->total_impressions;
|
||||
}
|
||||
|
||||
// 累加该月的 spend 和 conversions_value
|
||||
$chat_data[$month]['total_spend'] += $monthlyData['spend'];
|
||||
$chat_data[$month]['total_conversions_value'] += $monthlyData['conversions_value'];
|
||||
|
||||
// Aggregate statistics for overall summary
|
||||
$statistics['spend'] += $monthlyData['spend'];
|
||||
$statistics['conversions_value'] += $monthlyData['conversions_value'];
|
||||
// 计算 ROAS
|
||||
$roas = $assetSummaryData[$assetRelation->asset_id]['spend'] > 0 ?
|
||||
$assetSummaryData[$assetRelation->asset_id]['total_conversions_value'] / $assetSummaryData[$assetRelation->asset_id]['spend'] :
|
||||
0;
|
||||
$assetSummaryData[$assetRelation->asset_id]['roas'] = $roas > 0 ? number_format($roas, 2) . 'X' : '-';
|
||||
|
||||
// 填充 ad_count 和 creative_data
|
||||
$assetSummaryData[$assetRelation->asset_id]['ad_count'] = count($adStatsCollection);
|
||||
$assetSummaryData[$assetRelation->asset_id]['creative'] = $adStatsCollection[0]->ad_name; // 假设第一个 ad 的名称作为 creative_name
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// 计算每个月的总 ROAS,ROAS = 总的转换值 / 总的支出
|
||||
foreach ($chat_data as $month => $data) {
|
||||
// 计算 ROAS
|
||||
$totalSpend = $data['total_spend'];
|
||||
$totalConversionsValue = $data['total_conversions_value'];
|
||||
|
||||
// 如果有支出数据,计算 ROAS
|
||||
$chat_data[$month]['roas'] = $totalSpend ? ($totalConversionsValue / $totalSpend) : 0;
|
||||
// 格式化 ROAS 为倍数
|
||||
$chat_data[$month]['roas'] = round($chat_data[$month]['roas'], 2);
|
||||
}
|
||||
|
||||
// 计算整体的 ROAS
|
||||
$statistics['spend'] = '$' . number_format($statistics['spend'], 2);
|
||||
$statistics['roas'] = $statistics['spend'] > 0 ? ($statistics['conversions_value'] / $statistics['spend']) : 0;
|
||||
|
||||
|
||||
// 返回分页数据
|
||||
$totalItems = count($assetSummaryData);
|
||||
$totalPages = ceil($totalItems / $pageSize);
|
||||
$startIndex = ($page - 1) * $pageSize;
|
||||
// 截取返回的数据
|
||||
// $pagedData = array_slice($assetSummaryData, $startIndex, $pageSize);
|
||||
$resultDataPaginated = array_slice($resultData, ($page - 1) * $pageSize, $pageSize);
|
||||
|
||||
return [
|
||||
'data' => array_values($assetSummaryData),
|
||||
'total' => count($assetSummaryData),
|
||||
'statistics' => $statisticsData, // 汇总的统计数据
|
||||
'pagination' => [
|
||||
'startIndex' => $startIndex,
|
||||
'startIndex' => ($page - 1) * $pageSize,
|
||||
'maxResults' => $pageSize,
|
||||
'count' => $totalItems,
|
||||
'count' => count($assetSummaryData),
|
||||
'pageNo' => $page,
|
||||
'pageSize' => $pageSize,
|
||||
'pages' => $totalPages
|
||||
],
|
||||
'chat_1_data' => array_values($chat_data), // 返回按月汇总的 chat_data
|
||||
'data' => $resultDataPaginated,
|
||||
'statistics' => $statistics
|
||||
'pages' => ceil(count($assetSummaryData) / $pageSize)
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
public function getCreativeInsightData($platformType, $customerIds, $page, $pageSize, $keyword, $startDate = null, $endDate = null)
|
||||
{
|
||||
// 1. 创建查询对象,初始化 BpsAdCreativeInsight 查询
|
||||
$creativeDataQuery = BpsAdCreativeInsight::alias('i')
|
||||
->join('bps.bps_ads_creative c', 'i.creative_id = c.creative_id', 'LEFT') // 联接 bps_ads_creative 表
|
||||
->where('i.platform', $platformType); // 根据 platform 筛选
|
||||
|
||||
// 2. 日期范围筛选
|
||||
if ($startDate && $endDate) {
|
||||
$creativeDataQuery->whereBetween('i.date', [$startDate, $endDate]);
|
||||
}
|
||||
|
||||
// 3. 客户 ID 过滤(如果提供了)
|
||||
if (!empty($customerIds)) {
|
||||
$creativeDataQuery->whereIn('i.account_id', $customerIds);
|
||||
} else {
|
||||
return [
|
||||
'data' => [],
|
||||
'total' => 0,
|
||||
'statistics' => [],
|
||||
'pagination' => [
|
||||
'startIndex' => 0,
|
||||
'maxResults' => $pageSize,
|
||||
'count' => 0,
|
||||
'pageNo' => 1,
|
||||
'pageSize' => $pageSize
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
// 4. 关键词过滤
|
||||
if ($keyword) {
|
||||
$creativeDataQuery->where('c.name', 'like', '%' . $keyword . '%'); // 在 bps_ads_creative 表中查找关键词
|
||||
}
|
||||
|
||||
// 5. 数据聚合(按 creative_id 和其他字段)
|
||||
$creativeDataQuery->group('i.creative_id, i.platform, i.account_id, c.name, c.url, c.thumbnail_url') // 按需要的字段分组
|
||||
->field([
|
||||
'i.creative_id',
|
||||
'c.name AS creative_name', // 从 bps_ads_creative 表中选择 name
|
||||
'c.url AS creative_url', // 从 bps_ads_creative 表中选择 url
|
||||
'c.thumbnail_url', // 从 bps_ads_creative 表中选择 thumbnail_url
|
||||
ThinkDb::raw('SUM(i.spend) AS total_spend'),
|
||||
ThinkDb::raw('SUM(i.purchases_value) AS total_conversions_value'),
|
||||
ThinkDb::raw('SUM(i.purchases) AS total_conversions'),
|
||||
ThinkDb::raw('SUM(i.impressions) AS total_impressions'),
|
||||
ThinkDb::raw('SUM(i.clicks) AS total_clicks'),
|
||||
ThinkDb::raw('SUM(i.video_25) AS video_25'),
|
||||
ThinkDb::raw('SUM(i.video_50) AS video_50'),
|
||||
ThinkDb::raw('SUM(i.video_75) AS video_75'),
|
||||
ThinkDb::raw('SUM(i.video_100) AS video_100'),
|
||||
ThinkDb::raw('SUM(i.hold_rate) AS hold_rate')
|
||||
]);
|
||||
|
||||
// 6. 执行查询并获取聚合结果
|
||||
$aggregatedData = $creativeDataQuery->select();
|
||||
|
||||
// 7. 初始化广告创意的汇总数据和统计数据
|
||||
$creativeSummaryData = [];
|
||||
$statisticsData = $this->initializeStatistics();
|
||||
|
||||
// 8. 遍历查询结果并计算每个 creative 的相关统计数据
|
||||
foreach ($aggregatedData as $creativeData) {
|
||||
// 初始化该 creative_id 的数据(如果不存在)
|
||||
if (!isset($creativeSummaryData[$creativeData->creative_id])) {
|
||||
$creativeSummaryData[$creativeData->creative_id] = [
|
||||
'creative_id' => $creativeData->creative_id,
|
||||
'creative' => $creativeData->creative_name, // 使用联接查询中的 creative_name
|
||||
'creative_url' => $creativeData->creative_url, // 使用联接查询中的 creative_url
|
||||
'thumbnail_url' => $creativeData->thumbnail_url, // 使用联接查询中的 thumbnail_url
|
||||
'title' => $creativeData->title, // 使用联接查询中的 title
|
||||
'spend' => 0,
|
||||
'purchase_value' => '-',
|
||||
'roas' => 0,
|
||||
'cpa' => '-',
|
||||
'cpc_link_click' => '-',
|
||||
'cpm' => '-',
|
||||
'cpc_all' => '-',
|
||||
'aov' => '-',
|
||||
'click_to_atc_ratio' => '-',
|
||||
'atc_to_purchase_ratio' => '-',
|
||||
'purchases' => '-',
|
||||
'first_frame_retention' => '-',
|
||||
'thumbstop' => '-',
|
||||
'ctr_outbound' => '-',
|
||||
'click_to_purchase' => '-',
|
||||
'ctr_all' => '-',
|
||||
'video_plays_25_rate' => '-',
|
||||
'video_plays_50_rate' => '-',
|
||||
'video_plays_75_rate' => '-',
|
||||
'video_plays_100_rate' => '-',
|
||||
'hold_rate' => '-',
|
||||
'total_conversions_value' => 0,
|
||||
'total_conversions' => 0,
|
||||
'total_impressions' => 0,
|
||||
'ad_count' => 0
|
||||
];
|
||||
}
|
||||
|
||||
// 更新该 creative_id 的统计数据
|
||||
$creativeSummaryData[$creativeData->creative_id]['spend'] += $creativeData->total_spend;
|
||||
$creativeSummaryData[$creativeData->creative_id]['total_conversions_value'] += $creativeData->total_conversions_value;
|
||||
$creativeSummaryData[$creativeData->creative_id]['total_conversions'] += $creativeData->total_conversions;
|
||||
$creativeSummaryData[$creativeData->creative_id]['total_impressions'] += $creativeData->total_impressions;
|
||||
|
||||
// 汇总总体统计数据
|
||||
$statisticsData['spend'] += $creativeData->total_spend;
|
||||
$statisticsData['conversions_value'] += $creativeData->total_conversions_value;
|
||||
$statisticsData['total_conversions'] += $creativeData->total_conversions;
|
||||
$statisticsData['total_impressions'] += $creativeData->total_impressions;
|
||||
|
||||
// 计算 ROAS
|
||||
$roas = $creativeSummaryData[$creativeData->creative_id]['spend'] > 0
|
||||
? $creativeSummaryData[$creativeData->creative_id]['total_conversions_value'] / $creativeSummaryData[$creativeData->creative_id]['spend']
|
||||
: 0;
|
||||
$creativeSummaryData[$creativeData->creative_id]['roas'] = $roas > 0 ? number_format($roas, 2) . 'X' : '-';
|
||||
|
||||
// 填充广告计数
|
||||
$creativeSummaryData[$creativeData->creative_id]['ad_count'] = rand(10, 200); // 每个 creative_id 对应一个广告
|
||||
}
|
||||
|
||||
// 9. 返回分页数据
|
||||
return [
|
||||
'data' => array_values($creativeSummaryData),
|
||||
'total' => count($creativeSummaryData),
|
||||
'statistics' => $statisticsData, // 汇总的统计数据
|
||||
'pagination' => [
|
||||
'startIndex' => ($page - 1) * $pageSize,
|
||||
'maxResults' => $pageSize,
|
||||
'count' => count($creativeSummaryData),
|
||||
'pageNo' => $page,
|
||||
'pageSize' => $pageSize,
|
||||
'pages' => ceil(count($creativeSummaryData) / $pageSize)
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 初始化统计数据
|
||||
*/
|
||||
@ -992,4 +964,150 @@ class AdsInsightService
|
||||
// Add other stats as necessary
|
||||
];
|
||||
}
|
||||
|
||||
public function getAdcycleInsight($platformType, $customerIds, $cycle, $startDate = null, $endDate = null)
|
||||
{
|
||||
// 1. 查询全部数据集
|
||||
$adcycleDataQuery = BpsAdInsight::alias('i')
|
||||
->where('i.platform', $platformType); // 根据 platform 筛选
|
||||
//dump($customerIds);
|
||||
// 2. 客户 ID 过滤(如果提供了)
|
||||
if (!empty($customerIds)) {
|
||||
$adcycleDataQuery->whereIn('i.account_id', $customerIds);
|
||||
} else {
|
||||
return [
|
||||
'data' => [],
|
||||
'total' => 0
|
||||
];
|
||||
}
|
||||
|
||||
// 3. 时间范围筛选
|
||||
if ($startDate && $endDate) {
|
||||
$adcycleDataQuery->whereBetween('i.date', [$startDate, $endDate]);
|
||||
}
|
||||
|
||||
// 4. 获取数据并按日期聚合
|
||||
$adcycleData = $adcycleDataQuery->field([
|
||||
'i.date',
|
||||
ThinkDb::raw('COALESCE(SUM(i.spend) / 1000000, 0) as spend'),
|
||||
ThinkDb::raw('COALESCE(SUM(i.revenue), 0) as revenue')
|
||||
])
|
||||
->group('i.date') // 按日期进行分组
|
||||
->select();
|
||||
|
||||
// dump(ThinkDb::getLastSql());
|
||||
|
||||
// 5. 处理数据,按照周期进行分组
|
||||
$processedData = $this->processDataByCycle($adcycleData, $cycle);
|
||||
|
||||
// 6. 返回处理后的数据
|
||||
return $processedData;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按周期处理数据
|
||||
*
|
||||
* @param array $adcycleData 原始数据
|
||||
* @param string $cycle 周期类型(daily, weekly, monthly)
|
||||
* @return array 按照周期分组后的数据
|
||||
*/
|
||||
private function processDataByCycle($adcycleData, $cycle)
|
||||
{
|
||||
$groupedData = [];
|
||||
|
||||
foreach ($adcycleData as $data) {
|
||||
// 根据周期类型,调整日期分组
|
||||
switch ($cycle) {
|
||||
case 1:
|
||||
$key = $data->date; // 按日期直接分组
|
||||
break;
|
||||
case 2:
|
||||
// 使用 ISO 周格式来分组
|
||||
$key = $this->getWeekFromDate($data->date);
|
||||
break;
|
||||
case 3:
|
||||
// 按年-月格式分组
|
||||
$key = $this->getMonthFromDate($data->date);
|
||||
break;
|
||||
default:
|
||||
throw new \InvalidArgumentException("Invalid cycle value. Use 'daily', 'weekly' or 'monthly'.");
|
||||
}
|
||||
|
||||
// 汇总数据
|
||||
if (!isset($groupedData[$key])) {
|
||||
$groupedData[$key] = [
|
||||
'spend' => 0,
|
||||
'revenue' => 0,
|
||||
// 'conversions_value' => 0,
|
||||
// 'conversions' => 0,
|
||||
// 'impressions' => 0,
|
||||
// 'clicks' => 0
|
||||
];
|
||||
}
|
||||
|
||||
// 累加数据
|
||||
$groupedData[$key]['spend'] += $data->spend;
|
||||
$groupedData[$key]['revenue'] += $data->revenue;
|
||||
// $groupedData[$key]['conversions_value'] += $data->purchases_value;
|
||||
// $groupedData[$key]['conversions'] += $data->purchases;
|
||||
// $groupedData[$key]['impressions'] += $data->impressions;
|
||||
// $groupedData[$key]['clicks'] += $data->clicks;
|
||||
}
|
||||
|
||||
// 格式化返回数据
|
||||
$formattedData = [];
|
||||
foreach ($groupedData as $key => $values) {
|
||||
$roas = $values['spend'] > 0 ? $values['revenue'] / $values['spend'] : 0;
|
||||
$formattedData[] = [
|
||||
'date' => $key,
|
||||
'spend' => round($values['spend'], 2),
|
||||
'roas' => $roas > 0 ? round($roas, 2) : 0
|
||||
];
|
||||
}
|
||||
// 如果没有数据,返回空数组并提供默认的分页信息
|
||||
if (empty($formattedData)) {
|
||||
return [
|
||||
'data' => [],
|
||||
'total' => 0,
|
||||
];
|
||||
}
|
||||
|
||||
// 返回格式化后的数据
|
||||
return [
|
||||
'data' => $formattedData,
|
||||
'total' => count($formattedData),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取周数(基于 ISO 周格式)
|
||||
*
|
||||
* @param int $date 日期(格式:YYYYMMDD)
|
||||
* @return string ISO 周格式(YYYY-Www)
|
||||
*/
|
||||
private function getWeekFromDate($date)
|
||||
{
|
||||
// 将日期转换为 PHP DateTime 对象
|
||||
$dateStr = (string)$date;
|
||||
$dateObj = \DateTime::createFromFormat('Ymd', $dateStr);
|
||||
|
||||
// 获取 ISO 周格式
|
||||
return $dateObj->format('o-W');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取月分(格式:YYYY-MM)
|
||||
*
|
||||
* @param int $date 日期(格式:YYYYMMDD)
|
||||
* @return string 月份格式(YYYY-MM)
|
||||
*/
|
||||
private function getMonthFromDate($date)
|
||||
{
|
||||
// 将日期转换为 PHP DateTime 对象
|
||||
$dateStr = (string)$date;
|
||||
$dateObj = \DateTime::createFromFormat('Ymd', $dateStr);
|
||||
|
||||
// 获取年-月格式
|
||||
return $dateObj->format('Y-m');
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user