新增
This commit is contained in:
@@ -7,6 +7,9 @@ namespace app\adminapi\logic\order;
|
||||
use app\common\model\Order;
|
||||
use app\common\model\OrderDetail;
|
||||
use app\common\model\auth\Admin;
|
||||
use app\common\model\tcm\Diagnosis;
|
||||
use app\common\model\tcm\PrescriptionOrder;
|
||||
use app\common\model\tcm\PrescriptionOrderPayOrder;
|
||||
use app\common\service\wechat\WechatWorkExternalPayService;
|
||||
use think\facade\Db;
|
||||
use think\facade\Log;
|
||||
@@ -73,7 +76,7 @@ class OrderLogic
|
||||
|
||||
/**
|
||||
* @notes 从企业微信对外收款账单同步订单(员工直接在企业微信发起收款,未经过后台创建)
|
||||
* 拉取 get_bill_list 接口的已支付记录,创建或更新本地订单
|
||||
* 拉取 get_bill_list:trade_state 1=已完成(已支付) 3=已完成有退款;会创建订单,并在状态变化时更新(如已支付→已退款)
|
||||
* @param int $beginTime 开始时间戳(秒)
|
||||
* @param int $endTime 结束时间戳(秒)
|
||||
* @return array ['created' => int, 'updated' => int, 'skipped' => int, 'errors' => string[]]
|
||||
@@ -108,10 +111,13 @@ class OrderLogic
|
||||
|
||||
foreach ($billList as $bill) {
|
||||
$tradeState = (int)($bill['trade_state'] ?? 0);
|
||||
// 1:已完成(已支付) 3:已完成有退款 — 见企业微信 get_bill_list 文档
|
||||
if (!in_array($tradeState, [1, 3], true)) {
|
||||
$result['skipped']++;
|
||||
continue;
|
||||
}
|
||||
$targetStatus = $tradeState === 3 ? 4 : 2; // 4=已退款 2=已支付
|
||||
|
||||
$orderNo = (string)($bill['out_trade_no'] ?? $bill['trade_no'] ?? '');
|
||||
$totalFee = (int)($bill['total_fee'] ?? $bill['total_amount'] ?? 0);
|
||||
$tradeNo = (string)($bill['transaction_id'] ?? $bill['trade_no'] ?? '');
|
||||
@@ -134,34 +140,76 @@ class OrderLogic
|
||||
}
|
||||
|
||||
$payerExternalUserid = (string)($bill['external_userid'] ?? '');
|
||||
$paymentTimeStr = $payTime
|
||||
? (is_numeric($payTime) ? date('Y-m-d H:i:s', (int)$payTime) : (string)$payTime)
|
||||
: date('Y-m-d H:i:s');
|
||||
|
||||
$order = Order::where('order_no', $orderNo)->find();
|
||||
if ($order) {
|
||||
if ($order->status == 1) {
|
||||
$order->status = 2;
|
||||
$order->payment_method = 'wechat';
|
||||
$order->payment_time = $payTime ? (is_numeric($payTime) ? date('Y-m-d H:i:s', (int)$payTime) : $payTime) : date('Y-m-d H:i:s');
|
||||
$needSave = false;
|
||||
$currentStatus = (int)$order->status;
|
||||
|
||||
if ($currentStatus !== $targetStatus) {
|
||||
// 待支付:随账单变为已支付或已退款(含未同步到「已支付」即发生退款)
|
||||
if ($currentStatus === 1) {
|
||||
$order->status = $targetStatus;
|
||||
$needSave = true;
|
||||
} elseif ($currentStatus === 2 && $targetStatus === 4) {
|
||||
$order->status = 4;
|
||||
$needSave = true;
|
||||
} elseif ($currentStatus === 4 && $targetStatus === 2) {
|
||||
// 账单从「有退款」变回「已完成」等异常纠偏
|
||||
$order->status = 2;
|
||||
$needSave = true;
|
||||
}
|
||||
// 已取消(3) 不自动改支付状态,避免覆盖后台取消
|
||||
}
|
||||
|
||||
if ($currentStatus === 1 || $targetStatus === 2) {
|
||||
if ($order->payment_method !== 'wechat') {
|
||||
$order->payment_method = 'wechat';
|
||||
$needSave = true;
|
||||
}
|
||||
if ($paymentTimeStr !== '' && (string)$order->payment_time !== $paymentTimeStr) {
|
||||
$order->payment_time = $paymentTimeStr;
|
||||
$needSave = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($tradeNo !== '' && (string)$order->trade_no !== $tradeNo) {
|
||||
$order->trade_no = $tradeNo;
|
||||
$needSave = true;
|
||||
}
|
||||
|
||||
if (abs((float)$order->amount - $amount) > 0.000001) {
|
||||
$order->amount = $amount;
|
||||
$needSave = true;
|
||||
}
|
||||
|
||||
$defaultCreatorIdInt = (int)$defaultCreatorId;
|
||||
if ($billPayeeUserid && $creatorId !== $defaultCreatorIdInt && (int)$order->creator_id === $defaultCreatorIdInt) {
|
||||
$order->payee_userid = $billPayeeUserid;
|
||||
$order->payer_external_userid = $payerExternalUserid;
|
||||
$order->creator_id = $creatorId;
|
||||
$order->order_type = $orderType;
|
||||
$needSave = true;
|
||||
} elseif ($billPayeeUserid !== '' && (string)$order->payee_userid !== $billPayeeUserid) {
|
||||
$order->payee_userid = $billPayeeUserid;
|
||||
$needSave = true;
|
||||
}
|
||||
if ($payerExternalUserid !== '' && (string)$order->payer_external_userid !== $payerExternalUserid) {
|
||||
$order->payer_external_userid = $payerExternalUserid;
|
||||
$needSave = true;
|
||||
}
|
||||
|
||||
if ($amount == 5.00 && (int)$order->order_type !== 1) {
|
||||
$order->order_type = 1;
|
||||
$needSave = true;
|
||||
}
|
||||
|
||||
if ($needSave) {
|
||||
$order->save();
|
||||
$result['updated']++;
|
||||
} else {
|
||||
$needSave = false;
|
||||
if ($billPayeeUserid && $creatorId !== $defaultCreatorId && (int)$order->creator_id === $defaultCreatorId) {
|
||||
$order->payee_userid = $billPayeeUserid;
|
||||
$order->payer_external_userid = $payerExternalUserid;
|
||||
$order->creator_id = $creatorId;
|
||||
$needSave = true;
|
||||
}
|
||||
if ($amount == 5.00 && (int)$order->order_type !== 1) {
|
||||
$order->order_type = 1;
|
||||
$needSave = true;
|
||||
}
|
||||
if ($needSave) {
|
||||
$order->save();
|
||||
}
|
||||
$result['skipped']++;
|
||||
}
|
||||
} else {
|
||||
@@ -172,11 +220,18 @@ class OrderLogic
|
||||
$order->creator_id = $creatorId;
|
||||
$order->order_type = $orderType;
|
||||
$order->amount = $amount;
|
||||
$order->status = 2;
|
||||
$order->status = $targetStatus;
|
||||
$order->payment_method = 'wechat';
|
||||
$order->payment_time = $payTime ? (is_numeric($payTime) ? date('Y-m-d H:i:s', (int)$payTime) : $payTime) : date('Y-m-d H:i:s');
|
||||
$order->payment_time = $paymentTimeStr;
|
||||
$order->trade_no = $tradeNo;
|
||||
$order->remark = '企业微信直接收款同步,待关联患者';
|
||||
$remark = '企业微信直接收款同步,待关联患者';
|
||||
if ($tradeState === 3) {
|
||||
$refundCent = (int)($bill['total_refund_fee'] ?? 0);
|
||||
if ($refundCent > 0) {
|
||||
$remark .= '(账单含退款' . round($refundCent / 100, 2) . '元)';
|
||||
}
|
||||
}
|
||||
$order->remark = $remark;
|
||||
$order->payee_userid = $billPayeeUserid;
|
||||
$order->payer_external_userid = $payerExternalUserid;
|
||||
$order->save();
|
||||
@@ -652,15 +707,17 @@ class OrderLogic
|
||||
|
||||
/**
|
||||
* @notes 订单统计(按订单类型或退款)
|
||||
* @param array $params order_type(0退款,1挂号费,2问诊费,3药品费用,4首付,5尾款,6其他), days(0今天,7,30)
|
||||
* @param array $params order_type(-1全部已支付类型合计,0退款,1挂号费,2问诊费,3药品费用,4首付,5尾款,6其他), days(0今天,7,30)
|
||||
* @return array
|
||||
*/
|
||||
public static function orderStats(array $params = [])
|
||||
{
|
||||
$orderType = isset($params['order_type']) ? (int)$params['order_type'] : 1;
|
||||
if (!array_key_exists($orderType, self::$orderTypeNames)) {
|
||||
$allPaidOrderTypes = [1, 2, 3, 4, 5, 6];
|
||||
$orderType = array_key_exists('order_type', $params) ? (int) $params['order_type'] : 1;
|
||||
if ($orderType !== -1 && $orderType !== 0 && !array_key_exists($orderType, self::$orderTypeNames)) {
|
||||
$orderType = 1;
|
||||
}
|
||||
$orderTypeName = $orderType === -1 ? '全部(已支付)' : self::$orderTypeNames[$orderType];
|
||||
$days = isset($params['days']) ? (int)$params['days'] : 7;
|
||||
|
||||
$endTime = !empty($params['end_time']) ? strtotime($params['end_time']) : time();
|
||||
@@ -682,6 +739,8 @@ class OrderLogic
|
||||
->whereNull('delete_time');
|
||||
if ($orderType === 0) {
|
||||
$query->where('status', 4);
|
||||
} elseif ($orderType === -1) {
|
||||
$query->whereIn('order_type', $allPaidOrderTypes)->where('status', 2);
|
||||
} else {
|
||||
$query->where('order_type', $orderType)->where('status', 2);
|
||||
}
|
||||
@@ -696,7 +755,7 @@ class OrderLogic
|
||||
if (empty($creatorIds)) {
|
||||
return [
|
||||
'order_type' => $orderType,
|
||||
'order_type_name' => self::$orderTypeNames[$orderType],
|
||||
'order_type_name' => $orderTypeName,
|
||||
'date_range' => [date('Y-m-d', $startTime), date('Y-m-d', $endTime)],
|
||||
'today_total' => 0,
|
||||
'today_amount' => '0.00',
|
||||
@@ -738,6 +797,8 @@ class OrderLogic
|
||||
->whereNull('delete_time');
|
||||
if ($orderType === 0) {
|
||||
$todayQuery->where('status', 4);
|
||||
} elseif ($orderType === -1) {
|
||||
$todayQuery->whereIn('order_type', $allPaidOrderTypes)->where('status', 2);
|
||||
} else {
|
||||
$todayQuery->where('order_type', $orderType)->where('status', 2);
|
||||
}
|
||||
@@ -835,7 +896,7 @@ class OrderLogic
|
||||
|
||||
return [
|
||||
'order_type' => $orderType,
|
||||
'order_type_name' => self::$orderTypeNames[$orderType],
|
||||
'order_type_name' => $orderTypeName,
|
||||
'date_range' => [date('Y-m-d', $startTime), date('Y-m-d', $endTime)],
|
||||
'today_total' => $todayTotal,
|
||||
'today_amount' => number_format($todayAmount, 2, '.', ''),
|
||||
@@ -848,4 +909,129 @@ class OrderLogic
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 与订单列表一致:超管或主管角色可见他人创建的订单
|
||||
*/
|
||||
public static function isOrderListSupervisor(int $adminId, array $adminInfo): bool
|
||||
{
|
||||
if (!empty($adminInfo['root']) && (int) $adminInfo['root'] === 1) {
|
||||
return true;
|
||||
}
|
||||
$supervisorRoles = [0, 3];
|
||||
$myRoles = array_map('intval', $adminInfo['role_id'] ?? []);
|
||||
|
||||
return count(array_intersect($myRoles, $supervisorRoles)) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 某诊单下已支付支付单,供关联业务订单多选(主管/诊单医助看该诊单全部;否则仅本人创建)
|
||||
* 已占用(关联到未撤回/未取消的业务订单)的支付单会排除;编辑某业务订单时传 $exceptPrescriptionOrderId 以保留当前单已选中的项
|
||||
*
|
||||
* @return array<int, array<string, mixed>>
|
||||
*/
|
||||
public static function listPaidOrdersForDiagnosis(int $diagnosisId, int $adminId, array $adminInfo, ?int $exceptPrescriptionOrderId = null): array
|
||||
{
|
||||
if ($diagnosisId <= 0) {
|
||||
return [];
|
||||
}
|
||||
$exists = Diagnosis::where('id', $diagnosisId)->whereNull('delete_time')->count() > 0;
|
||||
if (!$exists) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$q = Order::where('patient_id', $diagnosisId)
|
||||
->where('status', 2)
|
||||
->whereNull('delete_time');
|
||||
|
||||
if (!self::isOrderListSupervisor($adminId, $adminInfo)) {
|
||||
$assistantId = (int) Diagnosis::where('id', $diagnosisId)->value('assistant_id');
|
||||
if ($assistantId !== $adminId) {
|
||||
$q->where('creator_id', $adminId);
|
||||
}
|
||||
}
|
||||
|
||||
$rows = $q
|
||||
->field(['id', 'order_no', 'order_type', 'amount', 'status', 'create_time', 'creator_id', 'remark'])
|
||||
->order('id', 'desc')
|
||||
->select()
|
||||
->toArray();
|
||||
|
||||
$activePoIds = PrescriptionOrder::whereNull('delete_time')
|
||||
->where('fulfillment_status', '<>', 4)
|
||||
->column('id');
|
||||
$busyPayIds = [];
|
||||
if ($activePoIds !== []) {
|
||||
$busyPayIds = PrescriptionOrderPayOrder::whereIn('prescription_order_id', $activePoIds)
|
||||
->column('pay_order_id');
|
||||
$busyPayIds = array_unique(array_map('intval', $busyPayIds));
|
||||
}
|
||||
$whiteList = [];
|
||||
if ($exceptPrescriptionOrderId !== null && $exceptPrescriptionOrderId > 0) {
|
||||
$whiteList = array_map(
|
||||
'intval',
|
||||
PrescriptionOrderPayOrder::where('prescription_order_id', $exceptPrescriptionOrderId)->column('pay_order_id')
|
||||
);
|
||||
}
|
||||
|
||||
$out = [];
|
||||
foreach ($rows as $row) {
|
||||
$oid = (int) ($row['id'] ?? 0);
|
||||
if ($oid <= 0) {
|
||||
continue;
|
||||
}
|
||||
$busy = in_array($oid, $busyPayIds, true);
|
||||
$allowed = in_array($oid, $whiteList, true);
|
||||
if ($busy && ! $allowed) {
|
||||
continue;
|
||||
}
|
||||
$out[] = $row;
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验支付单均可关联到指定诊单(已支付、归属与权限)
|
||||
*
|
||||
* @param int[] $ids zyt_order.id
|
||||
*/
|
||||
public static function assertPayOrdersLinkable(array $ids, int $diagnosisId, int $adminId, array $adminInfo): ?string
|
||||
{
|
||||
$ids = array_values(array_unique(array_filter(array_map('intval', $ids), static fn (int $v): bool => $v > 0)));
|
||||
if ($diagnosisId <= 0) {
|
||||
return '诊单无效';
|
||||
}
|
||||
if ($ids === []) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$diagExists = Diagnosis::where('id', $diagnosisId)->whereNull('delete_time')->count() > 0;
|
||||
if (!$diagExists) {
|
||||
return '诊单不存在';
|
||||
}
|
||||
|
||||
$supervisor = self::isOrderListSupervisor($adminId, $adminInfo);
|
||||
$assistantId = (int) Diagnosis::where('id', $diagnosisId)->value('assistant_id');
|
||||
$isDiagAssistant = $assistantId === $adminId;
|
||||
|
||||
$orders = Order::whereIn('id', $ids)->whereNull('delete_time')->select();
|
||||
if (count($orders) !== count($ids)) {
|
||||
return '部分支付单不存在或已删除';
|
||||
}
|
||||
|
||||
foreach ($orders as $o) {
|
||||
if ((int) $o->patient_id !== $diagnosisId) {
|
||||
return '支付单与诊单不匹配';
|
||||
}
|
||||
if ((int) $o->status !== 2) {
|
||||
return '仅能关联已支付订单';
|
||||
}
|
||||
if (! $supervisor && ! $isDiagAssistant && (int) $o->creator_id !== $adminId) {
|
||||
return '无权限关联所选支付单';
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user