This commit is contained in:
gr
2026-05-12 11:27:37 +08:00
3 changed files with 94 additions and 3 deletions
@@ -919,7 +919,8 @@ class PrescriptionOrderLists extends BaseAdminDataLists implements ListsSearchIn
YejiStatsLogic::applyPrescriptionOrderListAlignedWinnerDeptFilter(
$query,
(int) $this->params['assistant_dept_id'],
$yejiTableRowDeptIds
$yejiTableRowDeptIds,
$this->params['dept_ids'] ?? null
);
return;
@@ -2510,6 +2510,7 @@ class YejiStatsLogic
'patient_name' => (string) ($rw['patient_name'] ?? ''),
'patient_phone' => (string) ($rw['patient_phone'] ?? ''),
'doctor_name' => (string) ($rw['doctor_name'] ?? ''),
'assistant_name' => (string) ($rw['assistant_name'] ?? ''),
'channel_source' => $hasChSrc ? (string) ($rw['channel_source'] ?? '') : '',
];
}
@@ -2596,6 +2597,8 @@ class YejiStatsLogic
$q = Db::name('doctor_appointment')->alias('a')
->leftJoin('tcm_diagnosis u', 'a.patient_id = u.id')
->leftJoin('admin doc', 'a.doctor_id = doc.id AND doc.delete_time IS NULL')
->leftJoin('admin appt_asst', 'a.assistant_id = appt_asst.id AND appt_asst.delete_time IS NULL')
->leftJoin('admin diag_asst', 'u.assistant_id = diag_asst.id AND diag_asst.delete_time IS NULL')
->whereBetween('a.appointment_date', [$startDate, $endDate])
->whereIn('a.status', [1, 3, 4])
->whereRaw('(u.id IS NULL OR u.delete_time IS NULL)');
@@ -2638,6 +2641,7 @@ class YejiStatsLogic
'u.patient_name',
'u.phone AS patient_phone',
'doc.name AS doctor_name',
'COALESCE(appt_asst.name, diag_asst.name) AS assistant_name',
];
if ($hasChSrc) {
$fieldParts[] = 'a.channel_source';
@@ -2654,7 +2658,7 @@ class YejiStatsLogic
$lists = self::formatYejiAppointmentLinePayloadRows($rawList, $hasChSrc);
$note = '与业绩表「预约诊单」列同口径:预约日期在统计区间内,状态为已预约 / 已完成 / 已过号(不含已取消);部门归属医助优先,否则接诊医生。';
$note = '与业绩表「预约诊单」列同口径:预约日期在统计区间内,状态为已预约 / 已完成 / 已过号(不含已取消);部门归属医助优先,否则接诊医生;医助名与统计口径一致(挂号创建医助优先,否则诊单医助)。';
return [
'start_date' => (string) $c['startDate'],
@@ -2794,6 +2798,8 @@ class YejiStatsLogic
$q = Db::name('doctor_appointment')->alias('a')
->leftJoin('tcm_diagnosis u', 'a.patient_id = u.id')
->leftJoin('admin doc', 'a.doctor_id = doc.id AND doc.delete_time IS NULL')
->leftJoin('admin appt_asst', 'a.assistant_id = appt_asst.id AND appt_asst.delete_time IS NULL')
->leftJoin('admin diag_asst', 'u.assistant_id = diag_asst.id AND diag_asst.delete_time IS NULL')
->whereBetween('a.appointment_date', [$startDate, $endDate])
->whereIn('a.status', [1, 3, 4])
->whereRaw('(u.id IS NULL OR u.delete_time IS NULL)')
@@ -2824,6 +2830,7 @@ class YejiStatsLogic
'u.patient_name',
'u.phone AS patient_phone',
'doc.name AS doctor_name',
'COALESCE(appt_asst.name, diag_asst.name) AS assistant_name',
];
if ($hasChSrc) {
$fieldParts[] = 'a.channel_source';
@@ -2841,7 +2848,7 @@ class YejiStatsLogic
$lists = self::formatYejiAppointmentLinePayloadRows($rawList, $hasChSrc);
$note = '与排行榜「预约诊单」同口径:预约日期在统计区间内,状态为已预约 / 已完成 / 已过号(不含已取消);'
. '有效医助优先取挂号表创建医助,否则取诊单医助。';
. '有效医助优先取挂号表创建医助,否则取诊单医助(表中「医助」列与此一致)。';
return [
'start_date' => (string) $c['startDate'],
@@ -3400,6 +3407,88 @@ class YejiStatsLogic
return array_values(array_unique($out));
}
/**
* 处方订单列表(yeji_order_drawer=1 + yeji_table_row_dept_ids):assistant_dept_id 部门筛选与 {@see aggregateListAlignedOrderMetricsByDept}
* 一致——仅按订单创建人人事部门映射到当前表格展示行,命中多行取最深;只保留映射结果为 $winnerDeptId 的订单。
*
* @param Query $query tcm_prescription_order 主查询(无表别名)
* @param int[] $yejiTableRowDeptIds 请求 yeji_table_row_dept_ids
* @param int|string|array<int|string>|array<string>|null $yejiDeptIdsParam 请求 dept_ids,传入 {@see resolvePrimaryDepts}
*/
public static function applyPrescriptionOrderListAlignedWinnerDeptFilter(
Query $query,
int $winnerDeptId,
array $yejiTableRowDeptIds,
$yejiDeptIdsParam = null
): void {
$winnerDeptId = (int) $winnerDeptId;
$tableRowDeptIds = array_values(array_unique(array_filter(array_map('intval', $yejiTableRowDeptIds), static function (int $x): bool {
return $x > 0;
})));
if ($winnerDeptId <= 0 || $tableRowDeptIds === []) {
$query->whereRaw('0 = 1');
return;
}
if (!in_array($winnerDeptId, $tableRowDeptIds, true)) {
$query->whereRaw('0 = 1');
return;
}
[$primaryDeptIds, , , $deptById] = self::resolvePrimaryDepts($yejiDeptIdsParam);
$deptToDescendants = self::buildDeptDescendants($primaryDeptIds);
$adminToPrimary = self::buildAdminToPrimaryDept($primaryDeptIds, $deptToDescendants);
$childrenOf = self::yejiFullDeptChildrenOf();
/** @var array<int, array<int, true>> $rowSubtreeFlips */
$rowSubtreeFlips = [];
foreach ($tableRowDeptIds as $rid) {
$rid = (int) $rid;
if ($rid > 0) {
$rowSubtreeFlips[$rid] = self::yejiDeptSubtreeIdFlip($rid, $childrenOf);
}
}
$links = Db::name('admin_dept')->field(['admin_id', 'dept_id'])->select()->toArray();
/** @var array<int, int[]> $adminDeptIdList */
$adminDeptIdList = [];
foreach ($links as $l) {
$aid = (int) $l['admin_id'];
$did = (int) $l['dept_id'];
if ($aid > 0 && $did > 0) {
$adminDeptIdList[$aid][] = $did;
}
}
$candidateIds = array_values(array_unique(array_merge(array_keys($adminDeptIdList), array_keys($adminToPrimary))));
$allowedCreators = [];
foreach ($candidateIds as $aid) {
$aid = (int) $aid;
if ($aid <= 0) {
continue;
}
$mapped = self::resolveDeepestYejiTableRowForListDeptOr(
[$aid => true],
$adminDeptIdList,
$rowSubtreeFlips,
$tableRowDeptIds,
$deptById,
$adminToPrimary
);
if ($mapped === $winnerDeptId) {
$allowedCreators[] = $aid;
}
}
$allowedCreators = array_values(array_unique(array_filter($allowedCreators, static fn (int $x): bool => $x > 0)));
if ($allowedCreators === []) {
$query->whereRaw('0 = 1');
return;
}
$query->whereIn('creator_id', $allowedCreators);
}
/**
* 标签/医助兜底口径下的渠道向业绩全量 SUM(与 sumPerformance 的 scoped 分支同一组 WHERE,无部门归属过滤)。
*/