This commit is contained in:
Your Name
2026-07-09 11:24:18 +08:00
parent 6432e9990c
commit 0f33f2ad28
15 changed files with 450 additions and 22 deletions
@@ -15,6 +15,7 @@ use think\facade\Db;
* 同一诊单当月被多次指派给同一医助只计 1 次。
* - 第 N 次下单 = 诊单(患者)名下计入业绩的业务订单(剔除履约 4/9/10、软删)按 create_time 升序的**全局**序列中第 N 笔;
* 诊次**跨月累计不重置**:例如 5 月指派后旗下成交 4 单为二诊~五诊,6 月再成交即为六诊。
* 诊单可配置 `revisit_slot_start_offset`(默认 1:第 1 笔实单计为二诊;设为 2 则第 1 笔实单计为三诊,即在实单序号上叠加偏移,5 笔实单等价于计至七诊)。
* - 当月 N 诊单数 = **当月内下单**且全局序号为 N 的订单数,归属下单时点的**持有医助**——
* 按指派日志时间线取「订单时间之前最近一次指派」的 to_assistant_id(释放 to=0 即不再归属;
* 「继承」指派会转移持有人用于归属,但不计被指派数)。指派可发生在往月。
@@ -323,7 +324,7 @@ class RevisitRateLogic
* 核心统计上下文:
* 1. 全量指派日志(≤ 月末)构建持有时间线;
* 2. 分母:当月非继承指派的「医助 × 诊单」;
* 3. 分子:曾被指派诊单的当月订单按全局序号 ≥2 归属持有医助
* 3. 分子:曾被指派诊单的当月订单,统计诊次 = 实单序号 + 诊单偏移(默认第 1 笔实单为二诊)
* 4. 应用部门筛选(含组织下级)。
*
* @param array{month?:string,dept_ids?:int[]|string} $params
@@ -375,9 +376,10 @@ class RevisitRateLogic
}
}
// 分子:曾被指派诊单的当月订单(全局序号 ≥2),归属下单时点的持有医助
// 分子:曾被指派诊单的当月订单,统计诊次 = 实单全局序号 + 诊单偏移(默认偏移 1 → 第 1 笔实单为二诊)
/** @var array<int, array<int, list<array<string, mixed>>>> $slotOrdersByAssistant */
$slotOrdersByAssistant = [];
$offsetMap = self::fetchRevisitSlotStartOffsetMap(array_keys($candidateDiagSet));
foreach (array_chunk(array_keys($candidateDiagSet), 2000) as $chunk) {
$orderRows = self::fetchOrderSeqRows(
$chunk,
@@ -387,6 +389,7 @@ class RevisitRateLogic
$seq = 0;
$ptr = 0;
$holder = 0;
$offset = 1;
foreach ($orderRows as $r) {
$did = (int) ($r['diagnosis_id'] ?? 0);
if ($did <= 0) {
@@ -397,8 +400,10 @@ class RevisitRateLogic
$seq = 0;
$ptr = 0;
$holder = 0;
$offset = self::resolveRevisitSlotStartOffset($did, $offsetMap);
}
$seq++;
$effectiveSlot = $seq + $offset;
$ct = (int) ($r['create_time'] ?? 0);
// 推进时间线指针:订单时间之前(含同刻)最近一次指派的持有人
$tl = $timeline[$did] ?? [];
@@ -407,14 +412,14 @@ class RevisitRateLogic
$holder = (int) $tl[$ptr]['to'];
$ptr++;
}
if ($seq < 2 || $seq > self::MAX_VISIT_SLOT) {
if ($effectiveSlot < 2 || $effectiveSlot > self::MAX_VISIT_SLOT) {
continue;
}
if ($ct < $startTs || $ct > $endTs) {
continue;
}
if ($holder > 0) {
$slotOrdersByAssistant[$holder][$seq][] = $r;
$slotOrdersByAssistant[$holder][$effectiveSlot][] = $r;
}
}
}
@@ -619,6 +624,48 @@ class RevisitRateLogic
->toArray();
}
/**
* @param list<int> $diagIds
*
* @return array<int, int> diagnosis_id => revisit_slot_start_offset
*/
private static function fetchRevisitSlotStartOffsetMap(array $diagIds): array
{
if ($diagIds === []) {
return [];
}
$out = [];
foreach (array_chunk($diagIds, 2000) as $chunk) {
$rows = Db::name('tcm_diagnosis')
->whereIn('id', $chunk)
->whereNull('delete_time')
->column('revisit_slot_start_offset', 'id');
foreach ($rows as $id => $offset) {
$out[(int) $id] = (int) $offset;
}
}
return $out;
}
/**
* 诊单复诊统计起始偏移(默认 1:第 1 笔实单计为二诊;统计诊次 = 实单序号 + 偏移)
*
* @param array<int, int> $offsetMap
*/
private static function resolveRevisitSlotStartOffset(int $diagId, array $offsetMap): int
{
$offset = (int) ($offsetMap[$diagId] ?? 1);
if ($offset < 1) {
$offset = 1;
}
if ($offset > 20) {
$offset = 20;
}
return $offset;
}
/**
* @param list<int> $diagIds
*
@@ -748,6 +748,46 @@ class DiagnosisLogic extends BaseLogic
}
}
/**
* @notes 诊单指派医助操作记录列表
*/
public static function setRevisitSlotStartOffset(int $diagnosisId, int $offset, array $adminInfo): bool
{
self::$error = '';
if ($diagnosisId <= 0) {
self::setError('诊单不存在');
return false;
}
if ($offset < 1 || $offset > 20) {
self::setError('起始偏移须在 120 之间');
return false;
}
$diagnosis = Diagnosis::where('id', $diagnosisId)->whereNull('delete_time')->find();
if (!$diagnosis) {
self::setError('诊单不存在');
return false;
}
$old = (int) ($diagnosis->revisit_slot_start_offset ?? 1);
if ($old < 1) {
$old = 1;
}
if ($old === $offset) {
return true;
}
try {
$diagnosis->save(['revisit_slot_start_offset' => $offset]);
return true;
} catch (\Exception $e) {
self::setError($e->getMessage());
return false;
}
}
/**
* @notes 诊单指派医助操作记录列表
*/
@@ -3407,17 +3407,14 @@ class PrescriptionOrderLogic
}
/**
* 导出用:主方/辅方服用天数(优先业务订单 medication_days,缺省回退处方 usage_days / 辅方 aux_usage
* 导出用:主方/辅方开立天数(与详情侧栏「处方开立」同口径:主方取处方 usage_days辅方 aux_usage.usage_days
* 订单服用天数单独导出在 export_medication_days 列,不在此混用。
*
* @param array<string, mixed> $rx
* @param array<string, mixed>|null $auxUsage
*/
private static function resolveExportUsageDays(array $rx, ?array $auxUsage, $orderMedicationDays, bool $isAux): string
private static function resolveExportUsageDays(array $rx, ?array $auxUsage, bool $isAux): string
{
$medDays = $orderMedicationDays;
if ($medDays !== null && $medDays !== '' && (int) $medDays > 0) {
return (string) (int) $medDays;
}
if ($isAux) {
$days = (int) ($auxUsage['usage_days'] ?? 0);
@@ -3990,10 +3987,9 @@ class PrescriptionOrderLogic
} else {
$item['export_aux_usage'] = '';
}
$orderMedDays = $item['medication_days'] ?? null;
$item['export_main_usage_days'] = self::resolveExportUsageDays($rxArr, $auxUsageNorm, $orderMedDays, false);
$item['export_main_usage_days'] = self::resolveExportUsageDays($rxArr, $auxUsageNorm, false);
$item['export_aux_usage_days'] = $auxHerbs !== []
? self::resolveExportUsageDays($rxArr, $auxUsageNorm, $orderMedDays, true)
? self::resolveExportUsageDays($rxArr, $auxUsageNorm, true)
: '';
$item['export_service_package'] = self::formatServicePackageForExport(
@@ -4906,8 +4902,8 @@ class PrescriptionOrderLogic
return false;
}
if (in_array((int) $order->fulfillment_status, [3, 4], true)) {
self::setError('已完成或已取消的订单不可修改');
if ((int) $order->fulfillment_status === 4) {
self::setError('已取消的订单不可修改');
return false;
}