This commit is contained in:
Your Name
2026-10-17 16:51:48 +08:00
parent 56f85f7d89
commit ba2e2e4087
41 changed files with 2851 additions and 96 deletions
@@ -5763,7 +5763,7 @@ class PrescriptionOrderLogic
}
/**
* 业务订单详情场景:更新主方/辅方服用次数与开立天数,以及订单服用天数
* 业务订单详情场景:任意履约状态下更新主辅方服用参数,变更必须写入操作日志
*
* @param array<string, mixed> $params
*/
@@ -5774,7 +5774,8 @@ class PrescriptionOrderLogic
try {
return (bool) LockedPharmacySnapshotMutation::execute(
$prescriptionOrderId,
static fn (): bool => self::patchPrescriptionUsageLocked($params, $adminId, $adminInfo)
static fn (): bool => self::patchPrescriptionUsageLocked($params, $adminId, $adminInfo),
false // 服用参数允许在提交药房后修正,继续保留订单/提交记录行锁与事务。
);
} catch (\Throwable $exception) {
if (self::getError() === '') {
@@ -5799,21 +5800,13 @@ class PrescriptionOrderLogic
return false;
}
if (!self::assertRemoteSnapshotMutable($order)) {
return false;
}
if ((int) $order->fulfillment_status === 4) {
self::setError('已取消的订单不可修改');
return false;
}
$rxId = (int) ($order->prescription_id ?? 0);
if ($rxId <= 0) {
self::setError('该订单未关联处方');
return false;
}
$rx = Prescription::where('id', $rxId)->whereNull('delete_time')->find();
$rx = Prescription::where('id', $rxId)->whereNull('delete_time')->lock(true)->find();
if (!$rx) {
self::setError('处方不存在');
@@ -5828,25 +5821,37 @@ class PrescriptionOrderLogic
$timesPerDay = (int) ($params['times_per_day'] ?? 0);
$usageDays = (int) ($params['usage_days'] ?? 0);
$medDays = (int) ($params['medication_days'] ?? 0);
if ($timesPerDay < 1 || $timesPerDay > 6) {
if (!self::isPrescriptionUsageInteger($params['times_per_day'] ?? null, 6)) {
self::setError('主方每天次数须在 1~6 之间');
return false;
}
if ($usageDays < 1 || $usageDays > 999) {
if (!self::isPrescriptionUsageInteger($params['usage_days'] ?? null, 999)) {
self::setError('主方开立天数须在 1~999 之间');
return false;
}
if ($medDays < 1 || $medDays > 999) {
if (!self::isPrescriptionUsageInteger($params['medication_days'] ?? null, 999)) {
self::setError('订单服用天数须在 1~999 之间');
return false;
}
$isWaterPill = (string) $rx->prescription_type === '浓缩水丸';
$dosageBagCount = null;
if ($isWaterPill && array_key_exists('dosage_bag_count', $params)) {
if (!self::isPrescriptionUsageInteger($params['dosage_bag_count'], 5)) {
self::setError('主方袋数须为 1~5 的整数');
return false;
}
$dosageBagCount = (int) $params['dosage_bag_count'];
}
$hasAux = self::prescriptionHasAuxFormula($rx);
$auxTimesPerDay = null;
$auxUsageDays = null;
$auxDosageBagCount = null;
if ($hasAux) {
if (!array_key_exists('aux_times_per_day', $params) || !array_key_exists('aux_usage_days', $params)) {
self::setError('含辅方处方须填写辅方服用参数');
@@ -5855,20 +5860,29 @@ class PrescriptionOrderLogic
}
$auxTimesPerDay = (int) $params['aux_times_per_day'];
$auxUsageDays = (int) $params['aux_usage_days'];
if ($auxTimesPerDay < 1 || $auxTimesPerDay > 6) {
if (!self::isPrescriptionUsageInteger($params['aux_times_per_day'], 6)) {
self::setError('辅方每天次数须在 1~6 之间');
return false;
}
if ($auxUsageDays < 1 || $auxUsageDays > 999) {
if (!self::isPrescriptionUsageInteger($params['aux_usage_days'], 999)) {
self::setError('辅方开立天数须在 1~999 之间');
return false;
}
if ($isWaterPill && array_key_exists('aux_dosage_bag_count', $params)) {
if (!self::isPrescriptionUsageInteger($params['aux_dosage_bag_count'], 5)) {
self::setError('辅方袋数须为 1~5 的整数');
return false;
}
$auxDosageBagCount = (int) $params['aux_dosage_bag_count'];
}
}
$oldTimes = (int) ($rx->times_per_day ?? 0);
$oldUsageDays = (int) ($rx->usage_days ?? 0);
$oldDosageBagCount = max(1, (int) ($rx->dosage_bag_count ?? 1));
$oldMedDays = (int) ($order->medication_days ?? 0);
$oldAuxUsage = $rx->aux_usage;
if (is_string($oldAuxUsage)) {
@@ -5880,16 +5894,48 @@ class PrescriptionOrderLogic
}
$oldAuxTimes = (int) ($oldAuxUsage['times_per_day'] ?? 0);
$oldAuxUsageDays = (int) ($oldAuxUsage['usage_days'] ?? 0);
$oldAuxDosageBagCount = max(1, (int) ($oldAuxUsage['dosage_bag_count'] ?? 1));
$changes = [
'主方每天次数' => [$oldTimes, $timesPerDay, '次'],
'主方开立天数' => [$oldUsageDays, $usageDays, '天'],
];
if ($dosageBagCount !== null) {
$changes['主方袋数'] = [$oldDosageBagCount, $dosageBagCount, '袋'];
}
if ($hasAux) {
$changes['辅方每天次数'] = [$oldAuxTimes, $auxTimesPerDay, '次'];
$changes['辅方开立天数'] = [$oldAuxUsageDays, $auxUsageDays, '天'];
if ($auxDosageBagCount !== null) {
$changes['辅方袋数'] = [$oldAuxDosageBagCount, $auxDosageBagCount, '袋'];
}
}
$changes['订单服用天数'] = [$oldMedDays, $medDays, '天'];
$parts = [];
foreach ($changes as $label => [$oldValue, $newValue, $unit]) {
if ($oldValue !== $newValue) {
$parts[] = sprintf('%s %d%s → %d%s', $label, $oldValue, $unit, $newValue, $unit);
}
}
if ($parts === []) {
return true;
}
try {
$rxUpdates = [
'times_per_day' => $timesPerDay,
'usage_days' => $usageDays,
];
if ($dosageBagCount !== null) {
$rxUpdates['dosage_bag_count'] = $dosageBagCount;
}
if ($hasAux) {
$auxUsage = $oldAuxUsage;
$auxUsage['times_per_day'] = $auxTimesPerDay;
$auxUsage['usage_days'] = $auxUsageDays;
if ($auxDosageBagCount !== null) {
$auxUsage['dosage_bag_count'] = $auxDosageBagCount;
}
$rxUpdates['aux_usage'] = $auxUsage;
}
$rx->save($rxUpdates);
@@ -5897,31 +5943,8 @@ class PrescriptionOrderLogic
$order->medication_days = $medDays;
$order->save();
$parts = [
sprintf(
'主方 每天%d次/开立%d天 → 每天%d次/开立%d天',
$oldTimes > 0 ? $oldTimes : 0,
$oldUsageDays > 0 ? $oldUsageDays : 0,
$timesPerDay,
$usageDays
),
];
if ($hasAux) {
$parts[] = sprintf(
'辅方 每天%d次/开立%d天 → 每天%d次/开立%d天',
$oldAuxTimes > 0 ? $oldAuxTimes : 0,
$oldAuxUsageDays > 0 ? $oldAuxUsageDays : 0,
$auxTimesPerDay,
$auxUsageDays
);
}
$parts[] = sprintf(
'订单设置 %d天 → %d天',
$oldMedDays > 0 ? $oldMedDays : 0,
$medDays
);
$summary = '服用参数:' . implode(';', $parts);
self::writeLog($prescriptionOrderId, $adminId, $adminInfo, 'patch_rx_usage', $summary);
self::writeLog($prescriptionOrderId, $adminId, $adminInfo, 'patch_rx_usage', $summary, true);
return true;
} catch (\Exception $e) {
@@ -5931,6 +5954,13 @@ class PrescriptionOrderLogic
}
}
private static function isPrescriptionUsageInteger($value, int $max): bool
{
return (is_int($value) || is_string($value))
&& preg_match('/^[1-9][0-9]*$/D', (string) $value) === 1
&& (int) $value <= $max;
}
/**
* 处方是否含辅方药材(与列表/详情 has_aux_formula 口径一致)
*/