你好
This commit is contained in:
gr
2026-05-14 16:27:49 +08:00
286 changed files with 979 additions and 346 deletions
@@ -14,6 +14,7 @@ use app\common\model\tcm\Prescription;
use app\common\model\tcm\PrescriptionOrder;
use app\common\model\tcm\PrescriptionOrderLog;
use app\common\model\tcm\PrescriptionOrderPayOrder;
use app\common\model\dict\DictData;
use app\common\model\doctor\Appointment;
use app\common\model\auth\Admin;
use app\common\service\DataScope\DataScopeService;
@@ -1441,16 +1442,16 @@ class PrescriptionOrderLogic
return false;
}
// 已成功提交甘草 SCM(生成了甘草处方单号 或 submit_time>0),再改本地信息会与甘草侧不一致,禁止编辑
if ($fs === 6) {
self::$error = '已签收订单不可修改快递单号';
return false;
}
// 已成功提交甘草 SCM:仅允许更新快递单号与承运商(与甘草侧地址/药方等仍以取消流程为准)
$gcOrderNo = trim((string) $order->gancao_reciperl_order_no);
$gcSubmitTime = (int) $order->gancao_submit_time;
if ($gcOrderNo !== '' || $gcSubmitTime > 0) {
self::$error = sprintf(
'订单已提交甘草(处方单号:%s),不可再编辑;如需修改请先走取消流程',
$gcOrderNo !== '' ? $gcOrderNo : '—'
);
return false;
return self::editGancaoLogisticsOnly($order, $params, $adminId, $adminInfo);
}
$medDays = $params['medication_days'] ?? null;
@@ -1584,6 +1585,47 @@ class PrescriptionOrderLogic
return $out;
}
/**
* 甘草已提交后仅更新物流字段(tracking_number、express_company),忽略金额/地址等其它请求参数。
*
* @param array<string,mixed> $params
* @return array<string,mixed>|false
*/
private static function editGancaoLogisticsOnly(
PrescriptionOrder $order,
array $params,
int $adminId,
array $adminInfo
) {
$order->tracking_number = mb_substr(trim((string) ($params['tracking_number'] ?? '')), 0, 80);
if (array_key_exists('express_company', $params)) {
$order->express_company = self::normalizeExpressCompany($params['express_company']);
}
try {
$order->save();
} catch (\Throwable $e) {
self::$error = $e->getMessage();
return false;
}
self::writeLog(
(int) $order->id,
$adminId,
$adminInfo,
'edit',
'甘草订单已提交,仅更新快递信息(单号/承运商)'
);
$out = $order->toArray();
self::maskInternalCostIfNeeded($out, $adminInfo);
self::maskRemarkExtraIfNeeded($out, $adminInfo);
self::attachLinkedPayOrders($out);
return $out;
}
/**
* 确认发货:更新快递信息并将 fulfillment_status 从 2(履约中)推进到 5(已发货)
*
@@ -2485,6 +2527,60 @@ class PrescriptionOrderLogic
return $type;
}
/**
* 导出列:挂号表渠道来源展示(与 AppointmentLists channel_source_desc 同字典口径)
*
* @param array<string, mixed> $apRow doctor_appointment 一行
* @param array<string, string> $channelNameByValue DictData channels value=>name
*/
private static function formatGuahaoChannelSourceForExport(array $apRow, array $channelNameByValue): string
{
$srcKey = trim((string) ($apRow['channel_source'] ?? ''));
if ($srcKey === '' && isset($apRow['channels']) && $apRow['channels'] !== '' && $apRow['channels'] !== null) {
$srcKey = trim((string) $apRow['channels']);
}
$label = '';
if ($srcKey !== '') {
$label = (string) ($channelNameByValue[$srcKey] ?? $channelNameByValue[(string) (int) $srcKey] ?? $srcKey);
}
$detail = trim((string) ($apRow['channel_source_detail'] ?? ''));
if ($label === '' && $detail === '') {
return '';
}
if ($detail !== '') {
return $label !== '' ? "{$label}{$detail}" : $detail;
}
return $label;
}
/**
* 挂号表渠道相关列是否存在(未加 channel_source 的老库仅查 channels 或整列留空)
*
* @return array{channel_source: bool, channel_source_detail: bool, channels: bool}
*/
private static function doctorAppointmentChannelColumnsForExport(): array
{
$out = [
'channel_source' => false,
'channel_source_detail' => false,
'channels' => false,
];
try {
$cols = Db::name('doctor_appointment')->getTableFields();
if (!is_array($cols)) {
return $out;
}
foreach (array_keys($out) as $k) {
$out[$k] = in_array($k, $cols, true);
}
} catch (\Throwable) {
// keep false
}
return $out;
}
/**
* 业务订单列表导出:写入与 PrescriptionOrderLists::setExcelFields 对应的字段(export=2 时由列表类调用)
*
@@ -2524,6 +2620,39 @@ class PrescriptionOrderLogic
}
}
/** 诊单 ID => 该患者最近一条挂号(按预约日、id 倒序),用于导出「挂号渠道来源」 */
$apptChannelByDiagId = [];
$channelNameByValue = [];
$chCols = self::doctorAppointmentChannelColumnsForExport();
$needGuahaoChannel = $chCols['channel_source'] || $chCols['channels'] || $chCols['channel_source_detail'];
if ($diagIdList !== [] && $needGuahaoChannel) {
$selectFields = ['patient_id', 'appointment_date', 'id'];
if ($chCols['channel_source']) {
$selectFields[] = 'channel_source';
}
if ($chCols['channel_source_detail']) {
$selectFields[] = 'channel_source_detail';
}
if ($chCols['channels']) {
$selectFields[] = 'channels';
}
$apptRows = Appointment::whereIn('patient_id', $diagIdList)
->field($selectFields)
->order('appointment_date', 'desc')
->order('id', 'desc')
->select()
->toArray();
foreach ($apptRows as $ar) {
$p = (int) ($ar['patient_id'] ?? 0);
if ($p > 0 && !isset($apptChannelByDiagId[$p])) {
$apptChannelByDiagId[$p] = $ar;
}
}
if ($chCols['channel_source'] || $chCols['channels']) {
$channelNameByValue = DictData::where('type_value', 'channels')->column('name', 'value');
}
}
$rxById = [];
if ($rxIdList !== []) {
$rxRows = Prescription::whereIn('id', $rxIdList)->whereNull('delete_time')
@@ -2595,6 +2724,11 @@ class PrescriptionOrderLogic
$item['export_medication_form'] = self::formatMedicationFormForExport(\is_array($rx) ? $rx : []);
$item['export_channel'] = (string) ($item['service_channel'] ?? '');
$apCh = $apptChannelByDiagId[$diagId] ?? null;
$item['export_guahao_channel_source'] = \is_array($apCh)
? self::formatGuahaoChannelSourceForExport($apCh, $channelNameByValue)
: '';
$md = $item['medication_days'] ?? null;
$item['export_medication_days'] = $md !== null && $md !== '' ? (string) $md : '';