更新
This commit is contained in:
@@ -424,6 +424,15 @@ export function prescriptionOrderEdit(params: Record<string, unknown>) {
|
|||||||
return request.post({ url: '/tcm.prescriptionOrder/edit', params })
|
return request.post({ url: '/tcm.prescriptionOrder/edit', params })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 仅修改业务订单的承运商与快递单号;所有履约状态均可使用 */
|
||||||
|
export function prescriptionOrderDdcode(params: {
|
||||||
|
id: number
|
||||||
|
express_company: string
|
||||||
|
tracking_number: string
|
||||||
|
}) {
|
||||||
|
return request.post({ url: '/tcm.prescriptionOrder/ddcode', params })
|
||||||
|
}
|
||||||
|
|
||||||
/** 业务订单详情:仅修改关联处方的患者姓名与手机号 */
|
/** 业务订单详情:仅修改关联处方的患者姓名与手机号 */
|
||||||
export function prescriptionOrderPatchPrescriptionPatient(params: {
|
export function prescriptionOrderPatchPrescriptionPatient(params: {
|
||||||
id: number
|
id: number
|
||||||
|
|||||||
@@ -2255,6 +2255,7 @@ import {
|
|||||||
prescriptionOrderAuditPayment,
|
prescriptionOrderAuditPayment,
|
||||||
prescriptionOrderAuditPrescription,
|
prescriptionOrderAuditPrescription,
|
||||||
prescriptionOrderDetail,
|
prescriptionOrderDetail,
|
||||||
|
prescriptionOrderDdcode,
|
||||||
prescriptionOrderEdit,
|
prescriptionOrderEdit,
|
||||||
prescriptionOrderLists,
|
prescriptionOrderLists,
|
||||||
prescriptionOrderExport,
|
prescriptionOrderExport,
|
||||||
@@ -3243,9 +3244,8 @@ function canRefundRow(row: { fulfillment_status?: number; payment_slip_audit_sta
|
|||||||
return (fs === 5 || fs === 6 || fs === 3 || fs === 9) && Number(row.payment_slip_audit_status) === 1
|
return (fs === 5 || fs === 6 || fs === 3 || fs === 9) && Number(row.payment_slip_audit_status) === 1
|
||||||
}
|
}
|
||||||
|
|
||||||
function canQuickTrackRow(row: { fulfillment_status?: number }) {
|
function canQuickTrackRow(_row: { fulfillment_status?: number }) {
|
||||||
// 仅已发货(5) 可修改快递单号;已签收(6) 不可再改
|
return true
|
||||||
return Number(row.fulfillment_status) === 5
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function canUploadPharmacyRow(row: {
|
function canUploadPharmacyRow(row: {
|
||||||
@@ -4094,33 +4094,8 @@ async function submitQuickTrack() {
|
|||||||
}
|
}
|
||||||
quickTrackSaving.value = true
|
quickTrackSaving.value = true
|
||||||
try {
|
try {
|
||||||
// 先拉详情,获取所有必填字段,再只覆盖快递信息
|
await prescriptionOrderDdcode({
|
||||||
const res: any = await prescriptionOrderDetail({ id: quickTrackRowId.value })
|
id: quickTrackRowId.value,
|
||||||
const d = res?.data ?? res
|
|
||||||
if (!d) {
|
|
||||||
feedback.msgError('加载订单数据失败')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
await prescriptionOrderEdit({
|
|
||||||
id: d.id,
|
|
||||||
recipient_name: d.recipient_name || '',
|
|
||||||
recipient_phone: d.recipient_phone || '',
|
|
||||||
shipping_province: d.shipping_province || '',
|
|
||||||
shipping_city: d.shipping_city || '',
|
|
||||||
shipping_district: d.shipping_district || '',
|
|
||||||
shipping_address: d.shipping_address || '',
|
|
||||||
is_follow_up: d.is_follow_up ? 1 : 0,
|
|
||||||
medication_days: (d.medication_days != null && String(d.medication_days).trim() !== '') ? d.medication_days : '',
|
|
||||||
prev_staff: d.prev_staff || '',
|
|
||||||
service_channel: d.service_channel || '',
|
|
||||||
service_package: d.service_package || '',
|
|
||||||
fee_type: Number(d.fee_type) || 3,
|
|
||||||
amount: Number(d.amount) || 0,
|
|
||||||
remark_extra: d.remark_extra || '',
|
|
||||||
remark_assistant: d.remark_assistant || '',
|
|
||||||
internal_cost: (d.internal_cost != null && d.internal_cost !== '') ? d.internal_cost : '',
|
|
||||||
pay_order_ids: Array.isArray(d.pay_order_ids) ? d.pay_order_ids : [],
|
|
||||||
// 仅覆盖快递字段
|
|
||||||
express_company: quickTrackForm.express_company || 'auto',
|
express_company: quickTrackForm.express_company || 'auto',
|
||||||
tracking_number: quickTrackForm.tracking_number.trim()
|
tracking_number: quickTrackForm.tracking_number.trim()
|
||||||
})
|
})
|
||||||
@@ -4129,17 +4104,6 @@ async function submitQuickTrack() {
|
|||||||
getLists()
|
getLists()
|
||||||
// 若详情 Drawer 打开且是同一订单,同步刷新
|
// 若详情 Drawer 打开且是同一订单,同步刷新
|
||||||
await detailDrawerRef.value?.refreshIfCurrent(quickTrackRowId.value)
|
await detailDrawerRef.value?.refreshIfCurrent(quickTrackRowId.value)
|
||||||
// 仅保存前为履约中(2)时才询问确认发货;已发货(5)/已签收(6)等修改单号不再弹窗
|
|
||||||
if (canShipRow({ fulfillment_status: Number(d.fulfillment_status) })) {
|
|
||||||
try {
|
|
||||||
await ElMessageBox.confirm(
|
|
||||||
`快递单号「${quickTrackForm.tracking_number}」已保存,是否立即确认发货?`,
|
|
||||||
'确认发货',
|
|
||||||
{ type: 'success', confirmButtonText: '确认发货', cancelButtonText: '稍后再说' }
|
|
||||||
)
|
|
||||||
openShip({ id: quickTrackRowId.value, tracking_number: quickTrackForm.tracking_number, express_company: quickTrackForm.express_company })
|
|
||||||
} catch { /* 用户点了「稍后」 */ }
|
|
||||||
}
|
|
||||||
} catch {
|
} catch {
|
||||||
/* 拦截器已提示 */
|
/* 拦截器已提示 */
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -2713,6 +2713,7 @@ import {
|
|||||||
prescriptionOrderAuditPayment,
|
prescriptionOrderAuditPayment,
|
||||||
prescriptionOrderAuditPrescription,
|
prescriptionOrderAuditPrescription,
|
||||||
prescriptionOrderDetail,
|
prescriptionOrderDetail,
|
||||||
|
prescriptionOrderDdcode,
|
||||||
prescriptionOrderEdit,
|
prescriptionOrderEdit,
|
||||||
prescriptionOrderLists,
|
prescriptionOrderLists,
|
||||||
prescriptionOrderPaidPayOrders,
|
prescriptionOrderPaidPayOrders,
|
||||||
@@ -3551,8 +3552,8 @@ function canRefundRow(row: { fulfillment_status?: number; payment_slip_audit_sta
|
|||||||
return (fs === 5 || fs === 6 || fs === 3 || fs === 9) && Number(row.payment_slip_audit_status) === 1
|
return (fs === 5 || fs === 6 || fs === 3 || fs === 9) && Number(row.payment_slip_audit_status) === 1
|
||||||
}
|
}
|
||||||
|
|
||||||
function canQuickTrackRow(row: { fulfillment_status?: number }) {
|
function canQuickTrackRow(_row: { fulfillment_status?: number }) {
|
||||||
return Number(row.fulfillment_status) === 5
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
function canUploadPharmacyRow(row: {
|
function canUploadPharmacyRow(row: {
|
||||||
@@ -4900,33 +4901,8 @@ async function submitQuickTrack() {
|
|||||||
}
|
}
|
||||||
quickTrackSaving.value = true
|
quickTrackSaving.value = true
|
||||||
try {
|
try {
|
||||||
// 先拉详情,获取所有必填字段,再只覆盖快递信息
|
await prescriptionOrderDdcode({
|
||||||
const res: any = await prescriptionOrderDetail({ id: quickTrackRowId.value })
|
id: quickTrackRowId.value,
|
||||||
const d = res?.data ?? res
|
|
||||||
if (!d) {
|
|
||||||
feedback.msgError('加载订单数据失败')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
await prescriptionOrderEdit({
|
|
||||||
id: d.id,
|
|
||||||
recipient_name: d.recipient_name || '',
|
|
||||||
recipient_phone: d.recipient_phone || '',
|
|
||||||
shipping_province: d.shipping_province || '',
|
|
||||||
shipping_city: d.shipping_city || '',
|
|
||||||
shipping_district: d.shipping_district || '',
|
|
||||||
shipping_address: d.shipping_address || '',
|
|
||||||
is_follow_up: d.is_follow_up ? 1 : 0,
|
|
||||||
medication_days: (d.medication_days != null && String(d.medication_days).trim() !== '') ? d.medication_days : '',
|
|
||||||
prev_staff: d.prev_staff || '',
|
|
||||||
service_channel: d.service_channel || '',
|
|
||||||
service_package: d.service_package || '',
|
|
||||||
fee_type: Number(d.fee_type) || 3,
|
|
||||||
amount: Number(d.amount) || 0,
|
|
||||||
remark_extra: d.remark_extra || '',
|
|
||||||
remark_assistant: d.remark_assistant || '',
|
|
||||||
internal_cost: (d.internal_cost != null && d.internal_cost !== '') ? d.internal_cost : '',
|
|
||||||
pay_order_ids: Array.isArray(d.pay_order_ids) ? d.pay_order_ids : [],
|
|
||||||
// 仅覆盖快递字段
|
|
||||||
express_company: quickTrackForm.express_company || 'auto',
|
express_company: quickTrackForm.express_company || 'auto',
|
||||||
tracking_number: quickTrackForm.tracking_number.trim()
|
tracking_number: quickTrackForm.tracking_number.trim()
|
||||||
})
|
})
|
||||||
@@ -4939,19 +4915,9 @@ async function submitQuickTrack() {
|
|||||||
const r: any = await prescriptionOrderDetail({ id: quickTrackRowId.value })
|
const r: any = await prescriptionOrderDetail({ id: quickTrackRowId.value })
|
||||||
const nd = r?.data ?? r ?? null
|
const nd = r?.data ?? r ?? null
|
||||||
if (nd) detailData.value = nd
|
if (nd) detailData.value = nd
|
||||||
|
await fetchLogs(quickTrackRowId.value)
|
||||||
} catch { /* 静默 */ }
|
} catch { /* 静默 */ }
|
||||||
}
|
}
|
||||||
// 仅保存前为履约中(2)时才询问确认发货;已发货(5)/已签收(6)等修改单号不再弹窗
|
|
||||||
if (canShipRow({ fulfillment_status: Number(d.fulfillment_status) })) {
|
|
||||||
try {
|
|
||||||
await ElMessageBox.confirm(
|
|
||||||
`快递单号「${quickTrackForm.tracking_number}」已保存,是否立即确认发货?`,
|
|
||||||
'确认发货',
|
|
||||||
{ type: 'success', confirmButtonText: '确认发货', cancelButtonText: '稍后再说' }
|
|
||||||
)
|
|
||||||
openShip({ id: quickTrackRowId.value, tracking_number: quickTrackForm.tracking_number, express_company: quickTrackForm.express_company })
|
|
||||||
} catch { /* 用户点了「稍后」 */ }
|
|
||||||
}
|
|
||||||
} catch {
|
} catch {
|
||||||
/* 拦截器已提示 */
|
/* 拦截器已提示 */
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -131,6 +131,26 @@ class PrescriptionOrderController extends BaseAdminController
|
|||||||
return $this->success('保存成功', $result);
|
return $this->success('保存成功', $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 仅修改承运商与快递单号,不受订单履约状态或远端药房快照锁限制。
|
||||||
|
*/
|
||||||
|
public function ddcode()
|
||||||
|
{
|
||||||
|
$params = (new PrescriptionOrderValidate())->post()->goCheck('ddcode');
|
||||||
|
$result = PrescriptionOrderLogic::ddcode(
|
||||||
|
(int) $params['id'],
|
||||||
|
(string) ($params['express_company'] ?? 'auto'),
|
||||||
|
(string) $params['tracking_number'],
|
||||||
|
$this->adminId,
|
||||||
|
$this->adminInfo
|
||||||
|
);
|
||||||
|
if ($result === false) {
|
||||||
|
return $this->fail(PrescriptionOrderLogic::getError());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success('快递单号已保存', $result);
|
||||||
|
}
|
||||||
|
|
||||||
public function updateAmount()
|
public function updateAmount()
|
||||||
{
|
{
|
||||||
$params = (new PrescriptionOrderValidate())->post()->goCheck('updateAmount');
|
$params = (new PrescriptionOrderValidate())->post()->goCheck('updateAmount');
|
||||||
|
|||||||
@@ -1904,21 +1904,72 @@ class PrescriptionOrderLogic
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 甘草已提交后仅更新物流字段(tracking_number、express_company),忽略金额/地址等其它请求参数。
|
* 仅修改承运商与快递单号。物流信息不属于药房下单快照,因此允许在所有履约状态下修正。
|
||||||
*
|
*
|
||||||
* @param array<string,mixed> $params
|
|
||||||
* @return array<string,mixed>|false
|
* @return array<string,mixed>|false
|
||||||
*/
|
*/
|
||||||
private static function editGancaoLogisticsOnly(
|
public static function ddcode(
|
||||||
PrescriptionOrder $order,
|
int $id,
|
||||||
array $params,
|
string $expressCompany,
|
||||||
|
string $trackingNumber,
|
||||||
int $adminId,
|
int $adminId,
|
||||||
array $adminInfo
|
array $adminInfo
|
||||||
) {
|
) {
|
||||||
$order->tracking_number = mb_substr(trim((string) ($params['tracking_number'] ?? '')), 0, 80);
|
self::setError('');
|
||||||
if (array_key_exists('express_company', $params)) {
|
try {
|
||||||
$order->express_company = self::normalizeExpressCompany($params['express_company']);
|
return LockedPharmacySnapshotMutation::execute(
|
||||||
|
$id,
|
||||||
|
static fn () => self::ddcodeLocked(
|
||||||
|
$id,
|
||||||
|
$expressCompany,
|
||||||
|
$trackingNumber,
|
||||||
|
$adminId,
|
||||||
|
$adminInfo
|
||||||
|
),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
} catch (\Throwable $exception) {
|
||||||
|
if (self::getError() === '') {
|
||||||
|
self::setError($exception->getMessage());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return array<string,mixed>|false */
|
||||||
|
private static function ddcodeLocked(
|
||||||
|
int $id,
|
||||||
|
string $expressCompany,
|
||||||
|
string $trackingNumber,
|
||||||
|
int $adminId,
|
||||||
|
array $adminInfo
|
||||||
|
) {
|
||||||
|
self::$error = '';
|
||||||
|
$trackingNumber = mb_substr(trim($trackingNumber), 0, 80);
|
||||||
|
if ($trackingNumber === '') {
|
||||||
|
self::$error = '快递单号不能为空';
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$order = PrescriptionOrder::where('id', $id)->whereNull('delete_time')->find();
|
||||||
|
if (!$order) {
|
||||||
|
self::$error = '订单不存在';
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!self::canAccessOrder($order, $adminId, $adminInfo)) {
|
||||||
|
self::$error = '无权限操作';
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$oldTrackingNumber = trim((string) ($order->tracking_number ?? ''));
|
||||||
|
$oldExpressCompany = self::normalizeExpressCompany((string) ($order->express_company ?? 'auto'));
|
||||||
|
$newExpressCompany = self::normalizeExpressCompany($expressCompany);
|
||||||
|
|
||||||
|
$order->tracking_number = $trackingNumber;
|
||||||
|
$order->express_company = $newExpressCompany;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$order->save();
|
$order->save();
|
||||||
@@ -1932,8 +1983,15 @@ class PrescriptionOrderLogic
|
|||||||
(int) $order->id,
|
(int) $order->id,
|
||||||
$adminId,
|
$adminId,
|
||||||
$adminInfo,
|
$adminInfo,
|
||||||
'edit',
|
'fill_tracking',
|
||||||
'甘草订单已提交,仅更新快递信息(单号/承运商)'
|
sprintf(
|
||||||
|
'修改快递信息:单号「%s」→「%s」,承运商「%s」→「%s」',
|
||||||
|
$oldTrackingNumber !== '' ? $oldTrackingNumber : '空',
|
||||||
|
$trackingNumber,
|
||||||
|
$oldExpressCompany,
|
||||||
|
$newExpressCompany
|
||||||
|
),
|
||||||
|
true
|
||||||
);
|
);
|
||||||
|
|
||||||
$out = $order->toArray();
|
$out = $order->toArray();
|
||||||
@@ -5370,7 +5428,14 @@ class PrescriptionOrderLogic
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function writeLog(int $orderId, int $adminId, array $adminInfo, string $action, string $summary): void
|
private static function writeLog(
|
||||||
|
int $orderId,
|
||||||
|
int $adminId,
|
||||||
|
array $adminInfo,
|
||||||
|
string $action,
|
||||||
|
string $summary,
|
||||||
|
bool $strict = false
|
||||||
|
): void
|
||||||
{
|
{
|
||||||
$adminName = $adminInfo['name'] ?? '';
|
$adminName = $adminInfo['name'] ?? '';
|
||||||
if ($adminName === '' && $adminId > 0) {
|
if ($adminName === '' && $adminId > 0) {
|
||||||
@@ -5388,7 +5453,10 @@ class PrescriptionOrderLogic
|
|||||||
try {
|
try {
|
||||||
$log->save();
|
$log->save();
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
// 忽略日志写入错误
|
if ($strict) {
|
||||||
|
throw new \RuntimeException('操作日志写入失败,快递信息未保存', 0, $e);
|
||||||
|
}
|
||||||
|
// 非关键日志沿用历史容错行为
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ class PrescriptionOrderValidate extends BaseValidate
|
|||||||
'action.require' => '请选择审核操作',
|
'action.require' => '请选择审核操作',
|
||||||
'patient_name.require' => '请输入患者姓名',
|
'patient_name.require' => '请输入患者姓名',
|
||||||
'phone.require' => '请输入手机号',
|
'phone.require' => '请输入手机号',
|
||||||
|
'tracking_number.require' => '请输入快递单号',
|
||||||
'phone_tail.regex' => '手机后四位仅支持数字',
|
'phone_tail.regex' => '手机后四位仅支持数字',
|
||||||
'reason.require' => '请填写退款原因',
|
'reason.require' => '请填写退款原因',
|
||||||
];
|
];
|
||||||
@@ -75,6 +76,7 @@ class PrescriptionOrderValidate extends BaseValidate
|
|||||||
'is_follow_up', 'prev_staff', 'service_channel', 'service_package',
|
'is_follow_up', 'prev_staff', 'service_channel', 'service_package',
|
||||||
'tracking_number', 'express_company', 'fee_type', 'amount', 'remark_extra', 'remark_assistant', 'pay_order_ids',
|
'tracking_number', 'express_company', 'fee_type', 'amount', 'remark_extra', 'remark_assistant', 'pay_order_ids',
|
||||||
],
|
],
|
||||||
|
'ddcode' => ['id', 'tracking_number', 'express_company'],
|
||||||
'logisticsTrace' => ['id', 'phone_tail'],
|
'logisticsTrace' => ['id', 'phone_tail'],
|
||||||
'logisticsJdUpdate' => ['id'],
|
'logisticsJdUpdate' => ['id'],
|
||||||
'auditPrescription' => ['id', 'action', 'remark'],
|
'auditPrescription' => ['id', 'action', 'remark'],
|
||||||
@@ -106,6 +108,14 @@ class PrescriptionOrderValidate extends BaseValidate
|
|||||||
->append('amount', 'require|float|egt:0');
|
->append('amount', 'require|float|egt:0');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function ddcode(): PrescriptionOrderValidate
|
||||||
|
{
|
||||||
|
return $this->only(['id', 'tracking_number', 'express_company'])
|
||||||
|
->append('id', 'require|integer|gt:0')
|
||||||
|
->append('tracking_number', 'require|max:80')
|
||||||
|
->append('express_company', 'max:20');
|
||||||
|
}
|
||||||
|
|
||||||
public function patchPrescriptionUsage(): PrescriptionOrderValidate
|
public function patchPrescriptionUsage(): PrescriptionOrderValidate
|
||||||
{
|
{
|
||||||
return $this->only(['id', 'times_per_day', 'usage_days', 'medication_days', 'aux_times_per_day', 'aux_usage_days'])
|
return $this->only(['id', 'times_per_day', 'usage_days', 'medication_days', 'aux_times_per_day', 'aux_usage_days'])
|
||||||
|
|||||||
@@ -59,6 +59,17 @@ FROM DUAL
|
|||||||
WHERE @po_menu_id IS NOT NULL
|
WHERE @po_menu_id IS NOT NULL
|
||||||
AND NOT EXISTS (SELECT 1 FROM zyt_system_menu WHERE perms = 'tcm.prescriptionOrder/edit');
|
AND NOT EXISTS (SELECT 1 FROM zyt_system_menu WHERE perms = 'tcm.prescriptionOrder/edit');
|
||||||
|
|
||||||
|
INSERT INTO zyt_system_menu (
|
||||||
|
pid, type, name, icon, sort, perms, paths, component,
|
||||||
|
selected, params, is_cache, is_show, is_disable, create_time, update_time
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
@po_menu_id, 'A', '修改快递单号', '', 31, 'tcm.prescriptionOrder/ddcode', '', '',
|
||||||
|
'', '', 0, 1, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
|
||||||
|
FROM DUAL
|
||||||
|
WHERE @po_menu_id IS NOT NULL
|
||||||
|
AND NOT EXISTS (SELECT 1 FROM zyt_system_menu WHERE perms = 'tcm.prescriptionOrder/ddcode');
|
||||||
|
|
||||||
INSERT INTO zyt_system_menu (
|
INSERT INTO zyt_system_menu (
|
||||||
pid, type, name, icon, sort, perms, paths, component,
|
pid, type, name, icon, sort, perms, paths, component,
|
||||||
selected, params, is_cache, is_show, is_disable, create_time, update_time
|
selected, params, is_cache, is_show, is_disable, create_time, update_time
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
-- 处方业务订单:独立修改快递单号权限。
|
||||||
|
-- 执行后需在「角色权限」中为允许修改物流信息的角色勾选本按钮权限。
|
||||||
|
|
||||||
|
SET @po_menu_id := (
|
||||||
|
SELECT id
|
||||||
|
FROM zyt_system_menu
|
||||||
|
WHERE perms = 'tcm.prescriptionOrder/lists'
|
||||||
|
LIMIT 1
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO zyt_system_menu (
|
||||||
|
pid, type, name, icon, sort, perms, paths, component,
|
||||||
|
selected, params, is_cache, is_show, is_disable, create_time, update_time
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
@po_menu_id, 'A', '修改快递单号', '', 31,
|
||||||
|
'tcm.prescriptionOrder/ddcode', '', '',
|
||||||
|
'', '', 0, 1, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
|
||||||
|
FROM DUAL
|
||||||
|
WHERE @po_menu_id IS NOT NULL
|
||||||
|
AND NOT EXISTS (
|
||||||
|
SELECT 1 FROM zyt_system_menu WHERE perms = 'tcm.prescriptionOrder/ddcode'
|
||||||
|
);
|
||||||
@@ -23,6 +23,10 @@ $assertTrue(
|
|||||||
str_contains($controllerSource, 'confirmGancaoSubmission'),
|
str_contains($controllerSource, 'confirmGancaoSubmission'),
|
||||||
'admin API must expose an actionable Gancao reconciliation endpoint'
|
'admin API must expose an actionable Gancao reconciliation endpoint'
|
||||||
);
|
);
|
||||||
|
$assertTrue(
|
||||||
|
str_contains($controllerSource, 'public function ddcode()'),
|
||||||
|
'admin API must expose a dedicated tracking correction endpoint'
|
||||||
|
);
|
||||||
$assertTrue(
|
$assertTrue(
|
||||||
str_contains($migrationSource, '`lease_expires_at`'),
|
str_contains($migrationSource, '`lease_expires_at`'),
|
||||||
'pharmacy submission claims must persist an explicit lease expiry'
|
'pharmacy submission claims must persist an explicit lease expiry'
|
||||||
|
|||||||
@@ -799,14 +799,14 @@ $assertTrue(
|
|||||||
'remote payload must reload the canonical order after acquiring the durable claim'
|
'remote payload must reload the canonical order after acquiring the durable claim'
|
||||||
);
|
);
|
||||||
$assertTrue(
|
$assertTrue(
|
||||||
substr_count($prescriptionOrderLogicSource, 'LockedPharmacySnapshotMutation::execute(') >= 7,
|
substr_count($prescriptionOrderLogicSource, 'LockedPharmacySnapshotMutation::execute(') >= 8,
|
||||||
'order edit, patient, ship, withdraw, audit revoke, ship-mode and usage mutations must run inside locked snapshot transactions'
|
'order edit, logistics, patient, ship, withdraw, audit revoke, ship-mode and usage mutations must run inside locked snapshot transactions'
|
||||||
);
|
);
|
||||||
$assertTrue(
|
$assertTrue(
|
||||||
substr_count($prescriptionLogicSource, 'LockedPharmacySnapshotMutation::executeForPrescription(') >= 4,
|
substr_count($prescriptionLogicSource, 'LockedPharmacySnapshotMutation::executeForPrescription(') >= 4,
|
||||||
'prescription edit, patient patch, delete and void must lock every linked order and claim before saving'
|
'prescription edit, patient patch, delete and void must lock every linked order and claim before saving'
|
||||||
);
|
);
|
||||||
foreach (['patchPrescriptionPatient', 'edit', 'ship', 'withdraw', 'revokeRxAudit', 'setShipMode', 'patchPrescriptionUsage'] as $method) {
|
foreach (['patchPrescriptionPatient', 'edit', 'ddcode', 'ship', 'withdraw', 'revokeRxAudit', 'setShipMode', 'patchPrescriptionUsage'] as $method) {
|
||||||
$start = (int) strpos($prescriptionOrderLogicSource, 'public static function ' . $method . '(');
|
$start = (int) strpos($prescriptionOrderLogicSource, 'public static function ' . $method . '(');
|
||||||
$end = (int) strpos($prescriptionOrderLogicSource, 'private static function ' . $method . 'Locked(', $start);
|
$end = (int) strpos($prescriptionOrderLogicSource, 'private static function ' . $method . 'Locked(', $start);
|
||||||
$wrapperSource = substr($prescriptionOrderLogicSource, $start, $end - $start);
|
$wrapperSource = substr($prescriptionOrderLogicSource, $start, $end - $start);
|
||||||
@@ -844,6 +844,35 @@ $assertTrue(
|
|||||||
!str_contains($shipLockedSource, '->ship_mode ='),
|
!str_contains($shipLockedSource, '->ship_mode ='),
|
||||||
'shipping logistics must never overwrite the pharmacy target snapshot'
|
'shipping logistics must never overwrite the pharmacy target snapshot'
|
||||||
);
|
);
|
||||||
|
$ddcodeStart = (int) strpos($prescriptionOrderLogicSource, 'public static function ddcode(');
|
||||||
|
$ddcodeLockedStart = (int) strpos($prescriptionOrderLogicSource, 'private static function ddcodeLocked(', $ddcodeStart);
|
||||||
|
$ddcodeEnd = (int) strpos($prescriptionOrderLogicSource, 'public static function ship(', $ddcodeLockedStart);
|
||||||
|
$ddcodeWrapperSource = substr($prescriptionOrderLogicSource, $ddcodeStart, $ddcodeLockedStart - $ddcodeStart);
|
||||||
|
$ddcodeLockedSource = substr($prescriptionOrderLogicSource, $ddcodeLockedStart, $ddcodeEnd - $ddcodeLockedStart);
|
||||||
|
$assertTrue(
|
||||||
|
(bool) preg_match(
|
||||||
|
'/LockedPharmacySnapshotMutation::execute\(.*?self::ddcodeLocked\(.*?\),\s*false\s*\)/s',
|
||||||
|
$ddcodeWrapperSource
|
||||||
|
),
|
||||||
|
'tracking correction must keep row locks and transactions while bypassing only the remote snapshot mutability assertion'
|
||||||
|
);
|
||||||
|
preg_match_all('/\$order->([a-z_]+)\s*=/', $ddcodeLockedSource, $ddcodeAssignedFieldMatches);
|
||||||
|
$assertSame(
|
||||||
|
['tracking_number', 'express_company'],
|
||||||
|
array_values(array_unique($ddcodeAssignedFieldMatches[1] ?? [])),
|
||||||
|
'tracking correction must write only the tracking number and carrier fields'
|
||||||
|
);
|
||||||
|
$assertTrue(
|
||||||
|
!str_contains($ddcodeLockedSource, '$order->fulfillment_status')
|
||||||
|
&& !str_contains($ddcodeLockedSource, 'assertRemoteSnapshotMutable'),
|
||||||
|
'tracking correction must be available in every fulfillment state and for remotely submitted orders'
|
||||||
|
);
|
||||||
|
$assertTrue(
|
||||||
|
str_contains($ddcodeLockedSource, "'fill_tracking'")
|
||||||
|
&& str_contains($ddcodeLockedSource, "'修改快递信息:单号")
|
||||||
|
&& str_contains($ddcodeLockedSource, "\n true\n );"),
|
||||||
|
'tracking correction must append a strict operation log containing old and new logistics values'
|
||||||
|
);
|
||||||
$assertTrue(
|
$assertTrue(
|
||||||
substr_count($prescriptionLogicSource, 'remoteSnapshotLockErrorForPrescription') >= 2,
|
substr_count($prescriptionLogicSource, 'remoteSnapshotLockErrorForPrescription') >= 2,
|
||||||
'consumer prescription edit and patient patch must enforce the linked order snapshot lock'
|
'consumer prescription edit and patient patch must enforce the linked order snapshot lock'
|
||||||
@@ -1459,6 +1488,9 @@ $assertTrue(
|
|||||||
$tcmApi = (string) file_get_contents(dirname(__DIR__, 3) . '/admin/src/api/tcm.ts');
|
$tcmApi = (string) file_get_contents(dirname(__DIR__, 3) . '/admin/src/api/tcm.ts');
|
||||||
$desktopOrderPage = (string) file_get_contents(dirname(__DIR__, 3) . '/admin/src/views/consumer/prescription/order_list.vue');
|
$desktopOrderPage = (string) file_get_contents(dirname(__DIR__, 3) . '/admin/src/views/consumer/prescription/order_list.vue');
|
||||||
$mobileOrderPage = (string) file_get_contents(dirname(__DIR__, 3) . '/admin/src/views/consumer/prescription/order_list_h5.vue');
|
$mobileOrderPage = (string) file_get_contents(dirname(__DIR__, 3) . '/admin/src/views/consumer/prescription/order_list_h5.vue');
|
||||||
|
$ddcodeMigration = (string) file_get_contents(
|
||||||
|
dirname(__DIR__, 2) . '/sql/1.9.20260803/add_prescription_order_ddcode_menu.sql'
|
||||||
|
);
|
||||||
$gancaoReconcileComponent = (string) file_get_contents(
|
$gancaoReconcileComponent = (string) file_get_contents(
|
||||||
dirname(__DIR__, 3) . '/admin/src/views/consumer/prescription/components/GancaoSubmissionReconcileButton.vue'
|
dirname(__DIR__, 3) . '/admin/src/views/consumer/prescription/components/GancaoSubmissionReconcileButton.vue'
|
||||||
);
|
);
|
||||||
@@ -1486,6 +1518,18 @@ $assertTrue(
|
|||||||
str_contains($tcmApi, "url: '/tcm.prescriptionOrder/uploadToPharmacy'"),
|
str_contains($tcmApi, "url: '/tcm.prescriptionOrder/uploadToPharmacy'"),
|
||||||
'unified pharmacy API client must use the independently registered upload URI'
|
'unified pharmacy API client must use the independently registered upload URI'
|
||||||
);
|
);
|
||||||
|
$assertTrue(
|
||||||
|
str_contains($tcmApi, "url: '/tcm.prescriptionOrder/ddcode'")
|
||||||
|
&& str_contains($ddcodeMigration, "'tcm.prescriptionOrder/ddcode'"),
|
||||||
|
'tracking correction API and its dedicated permission must be registered together'
|
||||||
|
);
|
||||||
|
$assertTrue(
|
||||||
|
str_contains($desktopOrderPage, 'await prescriptionOrderDdcode({')
|
||||||
|
&& str_contains($mobileOrderPage, 'await prescriptionOrderDdcode({')
|
||||||
|
&& (bool) preg_match('/function canQuickTrackRow\([^)]*\)\s*\{\s*return true\s*\}/', $desktopOrderPage)
|
||||||
|
&& (bool) preg_match('/function canQuickTrackRow\([^)]*\)\s*\{\s*return true\s*\}/', $mobileOrderPage),
|
||||||
|
'desktop and mobile tracking correction must use the dedicated API in every fulfillment state'
|
||||||
|
);
|
||||||
$assertTrue(
|
$assertTrue(
|
||||||
str_contains($desktopOrderPage, "v-perms=\"['tcm.prescriptionOrder/uploadToPharmacy']\""),
|
str_contains($desktopOrderPage, "v-perms=\"['tcm.prescriptionOrder/uploadToPharmacy']\""),
|
||||||
'unified pharmacy buttons must require the new upload permission'
|
'unified pharmacy buttons must require the new upload permission'
|
||||||
|
|||||||
Reference in New Issue
Block a user