This commit is contained in:
Your Name
2026-08-31 15:17:34 +08:00
parent ed48f8be31
commit 456dd667df
439 changed files with 5720 additions and 422 deletions
@@ -799,6 +799,31 @@ class PrescriptionOrderLogic
return null;
}
/** 收款关联增删共用订单行锁,失败时连同金额和日志一起回滚。 */
private static function mutatePayOrderLinks(int $id, callable $mutation)
{
self::$error = '';
try {
return Db::transaction(static function () use ($id, $mutation) {
$order = PrescriptionOrder::where('id', $id)->whereNull('delete_time')->lock(true)->find();
if (!$order) {
throw new \DomainException('订单不存在');
}
$result = $mutation();
if ($result === false) {
throw new \RuntimeException(self::$error ?: '收款关联变更失败');
}
return $result;
});
} catch (\Throwable $e) {
if (self::$error === '') {
self::$error = $e->getMessage();
}
return false;
}
}
/**
* @param int[] $payOrderIds
*/
@@ -2729,6 +2754,14 @@ class PrescriptionOrderLogic
* @return array<string,mixed>|false
*/
public static function addPayOrder(array $params, int $adminId, array $adminInfo)
{
return self::mutatePayOrderLinks(
(int) ($params['id'] ?? 0),
static fn () => self::addPayOrderLocked($params, $adminId, $adminInfo)
);
}
private static function addPayOrderLocked(array $params, int $adminId, array $adminInfo)
{
self::$error = '';
$id = (int) $params['id'];
@@ -2833,6 +2866,14 @@ class PrescriptionOrderLogic
* @return array<string,mixed>|false
*/
public static function linkPayOrder(array $params, int $adminId, array $adminInfo)
{
return self::mutatePayOrderLinks(
(int) ($params['id'] ?? 0),
static fn () => self::linkPayOrderLocked($params, $adminId, $adminInfo)
);
}
private static function linkPayOrderLocked(array $params, int $adminId, array $adminInfo)
{
self::$error = '';
$id = (int) $params['id'];
@@ -2938,6 +2979,88 @@ class PrescriptionOrderLogic
return $out;
}
/**
* 移除单笔收款关联:保留原支付单、总金额与履约/审核状态,同步已付及代收金额。
* 普通订单 paid 按剩余有效收款重算;退款订单的 paid 保留退款后的余额口径。
*/
public static function unlinkPayOrder(array $params, int $adminId, array $adminInfo)
{
self::$error = '';
// 显式校验独立权限,菜单迁移未执行时也不能绕过鉴权中间件的默认放行逻辑。
if ((int) ($adminInfo['root'] ?? 0) !== 1
&& !in_array('tcm.prescriptionOrder/unlinkPayOrder', AuthLogic::getAuthByAdminId($adminId), true)) {
self::$error = '无权限移除收款关联';
return false;
}
return self::mutatePayOrderLinks(
(int) ($params['id'] ?? 0),
static fn () => self::unlinkPayOrderLocked($params, $adminId, $adminInfo)
);
}
private static function unlinkPayOrderLocked(array $params, int $adminId, array $adminInfo)
{
$id = (int) $params['id'];
$payOrderId = (int) ($params['pay_order_id'] ?? 0);
$order = PrescriptionOrder::where('id', $id)->whereNull('delete_time')->find();
if (!self::canAccessOrder($order, $adminId, $adminInfo)) {
self::$error = '无权限操作此订单';
return false;
}
if (in_array((int) $order->fulfillment_status, [3, 4], true)) {
self::$error = '已完成或已取消的订单不允许移除收款关联';
return false;
}
if (!in_array($payOrderId, self::linkedPayOrderIdList($id), true)) {
self::$error = '该收款记录未关联当前订单,请刷新后重试';
return false;
}
$payOrder = Order::where('id', $payOrderId)->whereNull('delete_time')->lock(true)->find();
if (!$payOrder || !in_array((int) $payOrder->status, [2, 5], true)) {
self::$error = '仅已支付或待审核的收款记录可移除,已退款记录不可移除';
return false;
}
$oldPaidCents = (int) round((float) $order->paid * 100);
$removedCents = (int) round((float) $payOrder->amount * 100);
if ($removedCents < 0) {
self::$error = '收款金额异常,请先核对金额';
return false;
}
$deleted = PrescriptionOrderPayOrder::where('prescription_order_id', $id)
->where('pay_order_id', $payOrderId)->delete();
if ($deleted !== 1) {
throw new \RuntimeException('收款关联已变化,请刷新后重试');
}
$remainingIds = self::linkedPayOrderIdList($id);
$remainingPaidCents = $remainingIds === [] ? 0 : (int) round((float) Order::whereIn('id', $remainingIds)
->whereNull('delete_time')->whereIn('status', [2, 5])->sum('amount') * 100);
$order->linked_pay_order_id = $remainingIds[0] ?? null;
// 部分退款可能未拆分收款单金额,不能用剩余收款原额覆盖退款后的 paid 余额。
$hasRefund = (float) ($order->refund_amount ?? 0) > 0 || (int) $order->fulfillment_status === 10;
$newPaidCents = $hasRefund
? min($remainingPaidCents, max(0, $oldPaidCents - $removedCents))
: $remainingPaidCents;
$order->paid = $newPaidCents / 100;
// 与详情的关联已付总额口径一致;订单 amount 不变。
$order->agency_collect_amount = round((float) $order->amount - $remainingPaidCents / 100, 2);
$order->save();
self::writeLog($id, $adminId, $adminInfo, 'unlink_pay_order', sprintf(
'移除收款关联 #%d(%s,¥%.2f),订单总金额 ¥%.2f 不变;已付金额(paid)¥%.2f → ¥%.2f;原收款记录保留',
$payOrderId, (string) $payOrder->order_no, $removedCents / 100,
(float) $order->amount, $oldPaidCents / 100, $newPaidCents / 100
), true);
$out = PrescriptionOrder::where('id', $id)->find()->toArray();
self::maskInternalCostIfNeeded($out, $adminInfo);
self::maskRemarkExtraIfNeeded($out, $adminInfo);
self::attachLinkedPayOrders($out);
return $out;
}
/**
* 已发货/已签收订单:不新增/关联支付单,仅提交完单申请并将支付审核置为待审核。
*
@@ -5484,7 +5607,7 @@ class PrescriptionOrderLogic
$log->save();
} catch (\Throwable $e) {
if ($strict) {
throw new \RuntimeException('操作日志写入失败,快递信息未保存', 0, $e);
throw new \RuntimeException('操作日志写入失败,变更未保存', 0, $e);
}
// 非关键日志沿用历史容错行为
}