This commit is contained in:
Your Name
2026-08-18 14:08:38 +08:00
parent 8b9df1154c
commit bc1228a310
77 changed files with 10763 additions and 1181 deletions
@@ -62,7 +62,9 @@ class ConversionLogic
if ($mediaChannel === null && $requestedMediaChannelCode !== '') {
$mediaChannel = MediaChannelService::getChannelByCode($requestedMediaChannelCode);
}
$mediaChannelCode = $mediaChannel !== null ? $requestedMediaChannelCode : '';
$mediaChannelCodes = $mediaChannel !== null
? MediaChannelService::getChannelCodesForStats($mediaChannel)
: null;
$filterEmptyEntities = $mediaChannel !== null;
[$startTimestamp, $endTimestamp, $startDate, $endDate] = self::resolveTimeRange($params);
$pageNo = max(1, (int)($params['page_no'] ?? 1));
@@ -188,11 +190,11 @@ class ConversionLogic
);
// 数据隔离:可见部门 = 可见 admin 所属部门并集;用于 account_cost 与下游 cost 分摊。
$visibleDeptIds = self::resolveVisibleDeptIds($visibleAdminIds);
[$globalAccountCost, $accountCostDeptIds] = self::hydrateAccountCostStats($entities, $startDate, $endDate, $mediaChannelCode, $visibleDeptIds);
[$globalAccountCost, $accountCostDeptIds] = self::hydrateAccountCostStats($entities, $startDate, $endDate, $mediaChannelCodes, $visibleDeptIds);
$supportsDeptBinding = AccountCost::supportsDeptBinding();
$restrictAccountCostByDept = $supportsDeptBinding;
$channelBoundDeptIds = $supportsDeptBinding && $mediaChannelCode !== ''
? self::loadChannelBoundDeptIds($mediaChannelCode)
$channelBoundDeptIds = $supportsDeptBinding && $mediaChannelCodes !== null && $mediaChannelCodes !== []
? self::loadChannelBoundDeptIds($mediaChannelCodes)
: [];
// 渠道尚未维护投放成本时,不能把真实的加粉、挂号和订单一并过滤为空。
// 已维护绑定关系的渠道继续按绑定部门收窄;成本本身仍只在实际成本部门内分摊。
@@ -267,7 +269,7 @@ class ConversionLogic
$startDate,
$endDate,
$mediaChannel,
$mediaChannelCode,
$mediaChannelCodes,
$restrictAccountCostByDept,
$eligibleDeptIds,
$adminToDeptIds,
@@ -824,17 +826,18 @@ class ConversionLogic
/**
* 渠道绑定部门不依赖当前统计区间,避免某天没有录入成本时把统计实体过滤为空。
*
* @param string[] $mediaChannelCodes
* @return int[]
*/
private static function loadChannelBoundDeptIds(string $mediaChannelCode): array
private static function loadChannelBoundDeptIds(array $mediaChannelCodes): array
{
$mediaChannelCode = trim($mediaChannelCode);
if ($mediaChannelCode === '' || !AccountCost::supportsDeptBinding()) {
$mediaChannelCodes = self::normalizeMediaChannelCodes($mediaChannelCodes);
if ($mediaChannelCodes === [] || !AccountCost::supportsDeptBinding()) {
return [];
}
$deptIds = Db::name('account_cost')
->where('media_channel_code', $mediaChannelCode)
->whereIn('media_channel_code', $mediaChannelCodes)
->where('dept_id', '>', 0)
->distinct(true)
->column('dept_id');
@@ -1596,6 +1599,7 @@ class ConversionLogic
* 账户消耗:来源于独立维护表 zyt_account_cost。
*
* @param array<int, array<string, mixed>> $entities
* @param string[]|null $mediaChannelCodes null=不按渠道过滤;[]=已选渠道但无匹配 code,成本记 0
* @param int[]|null $visibleDeptIds 可见部门集合(null = SCOPE_ALL,不收窄)
* @return array{0: float, 1: int[]}
*/
@@ -1603,10 +1607,21 @@ class ConversionLogic
array &$entities,
string $startDate,
string $endDate,
string $mediaChannelCode,
?array $mediaChannelCodes,
?array $visibleDeptIds = null
): array
{
$mediaChannelCodes = $mediaChannelCodes === null ? null : self::normalizeMediaChannelCodes($mediaChannelCodes);
if ($mediaChannelCodes === []) {
foreach ($entities as &$entity) {
$entity['account_cost'] = 0.0;
$entity['_global_account_cost'] = 0.0;
}
unset($entity);
return [0.0, []];
}
$supportsDeptBinding = AccountCost::supportsDeptBinding();
$query = Db::name('account_cost')
->where('cost_date', '>=', $startDate)
@@ -1618,8 +1633,8 @@ class ConversionLogic
$query->field('amount');
}
if ($mediaChannelCode !== '') {
$query->where('media_channel_code', $mediaChannelCode);
if ($mediaChannelCodes !== null) {
$query->whereIn('media_channel_code', $mediaChannelCodes);
}
if ($supportsDeptBinding) {
@@ -2049,7 +2064,7 @@ class ConversionLogic
string $startDate,
string $endDate,
?array $mediaChannel,
string $mediaChannelCode,
?array $mediaChannelCodes,
bool $restrictAccountCostByDept,
array $eligibleDeptIds,
array $adminToDeptIds,
@@ -2081,9 +2096,9 @@ class ConversionLogic
if ($globalAccountCost < 0) {
// 任选一个非空 entity 集合查一次即可——查询本身只与日期 / 渠道相关。
if ($assistantIds !== []) {
[$globalAccountCost] = self::hydrateAccountCostStats($assistantEntities, $startDate, $endDate, $mediaChannelCode);
[$globalAccountCost] = self::hydrateAccountCostStats($assistantEntities, $startDate, $endDate, $mediaChannelCodes);
} elseif ($doctorIds !== []) {
[$globalAccountCost] = self::hydrateAccountCostStats($doctorEntities, $startDate, $endDate, $mediaChannelCode);
[$globalAccountCost] = self::hydrateAccountCostStats($doctorEntities, $startDate, $endDate, $mediaChannelCodes);
} else {
$globalAccountCost = 0.0;
}
@@ -2905,10 +2920,29 @@ class ConversionLogic
return [
'code' => (string)($mediaChannel['channel_code'] ?? ''),
'tag_id' => (string)($mediaChannel['source_tag_id'] ?? ''),
'tag_ids' => $mediaChannel['source_tag_ids'] ?? [],
'tag_name' => (string)($mediaChannel['source_tag_name'] ?? ''),
];
}
/**
* @param string|string[] $mediaChannelCode
* @return string[]
*/
private static function normalizeMediaChannelCodes(string|array $mediaChannelCode): array
{
$values = is_array($mediaChannelCode) ? $mediaChannelCode : [$mediaChannelCode];
$codes = [];
foreach ($values as $value) {
$code = trim((string)$value);
if ($code !== '' && !str_starts_with($code, MediaChannelService::GROUP_CODE_PREFIX)) {
$codes[$code] = $code;
}
}
return array_values($codes);
}
/**
* @param int[]|null $visibleAdminIds
* @param int[] $eligibleDeptIds