781 lines
26 KiB
PHP
781 lines
26 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace app\adminapi\logic\tcm;
|
|
|
|
use app\adminapi\logic\order\OrderLogic;
|
|
use app\common\model\Order;
|
|
use app\common\model\tcm\Diagnosis;
|
|
use app\common\model\tcm\PrescriptionOrder;
|
|
use app\common\model\tcm\PrescriptionOrderPayOrder;
|
|
use app\common\service\ExpressTrackService;
|
|
use think\facade\Config;
|
|
|
|
class PrescriptionOrderLogic
|
|
{
|
|
private static string $error = '';
|
|
|
|
public static function setError(string $msg): void
|
|
{
|
|
self::$error = $msg;
|
|
}
|
|
|
|
public static function getError(): string
|
|
{
|
|
return self::$error;
|
|
}
|
|
|
|
/**
|
|
* @param int[] $allowRoleIds
|
|
*/
|
|
private static function roleIntersect(array $adminInfo, array $allowRoleIds): bool
|
|
{
|
|
$myRoles = array_map('intval', $adminInfo['role_id'] ?? []);
|
|
$allow = array_map('intval', $allowRoleIds);
|
|
|
|
return count(array_intersect($myRoles, $allow)) > 0;
|
|
}
|
|
|
|
/** 与 order 列表一致:超管或 order_edit_all_roles 可见全部业务订单 */
|
|
public static function canSeeAllPrescriptionOrders(array $adminInfo): bool
|
|
{
|
|
if (!empty($adminInfo['root']) && (int) $adminInfo['root'] === 1) {
|
|
return true;
|
|
}
|
|
$roles = Config::get('project.order_edit_all_roles', [0, 3]);
|
|
|
|
return self::roleIntersect($adminInfo, is_array($roles) ? $roles : []);
|
|
}
|
|
|
|
/**
|
|
* @param PrescriptionOrder $row
|
|
*/
|
|
public static function canAccessOrder($row, int $adminId, array $adminInfo): bool
|
|
{
|
|
if (self::canSeeAllPrescriptionOrders($adminInfo)) {
|
|
return true;
|
|
}
|
|
if ((int) $row->creator_id === $adminId) {
|
|
return true;
|
|
}
|
|
$aid = (int) Diagnosis::where('id', (int) $row->diagnosis_id)->whereNull('delete_time')->value('assistant_id');
|
|
|
|
return $aid === $adminId;
|
|
}
|
|
|
|
/**
|
|
* @param PrescriptionOrder $row
|
|
*/
|
|
public static function canWithdrawOrder($row, int $adminId, array $adminInfo): bool
|
|
{
|
|
return self::canAccessOrder($row, $adminId, $adminInfo);
|
|
}
|
|
|
|
public static function canViewInternalCost(array $adminInfo): bool
|
|
{
|
|
if (!empty($adminInfo['root']) && (int) $adminInfo['root'] === 1) {
|
|
return true;
|
|
}
|
|
$allow = Config::get('project.prescription_order_finance_roles', [0, 3]);
|
|
$allow = array_map('intval', is_array($allow) ? $allow : []);
|
|
$myRoles = array_map('intval', $adminInfo['role_id'] ?? []);
|
|
|
|
return count(array_intersect($myRoles, $allow)) > 0;
|
|
}
|
|
|
|
public static function canAuditPrescriptionOrder(array $adminInfo): bool
|
|
{
|
|
if (!empty($adminInfo['root']) && (int) $adminInfo['root'] === 1) {
|
|
return true;
|
|
}
|
|
$allow = Config::get('project.prescription_audit_roles', [0, 3, 6]);
|
|
|
|
return self::roleIntersect($adminInfo, is_array($allow) ? $allow : []);
|
|
}
|
|
|
|
public static function canAuditPaymentSlipOrder(array $adminInfo): bool
|
|
{
|
|
if (!empty($adminInfo['root']) && (int) $adminInfo['root'] === 1) {
|
|
return true;
|
|
}
|
|
$allow = Config::get('project.prescription_order_payment_audit_roles', [0, 3]);
|
|
|
|
return self::roleIntersect($adminInfo, is_array($allow) ? $allow : []);
|
|
}
|
|
|
|
/**
|
|
* @param array<string,mixed> $row
|
|
*/
|
|
public static function maskInternalCostIfNeeded(array &$row, array $adminInfo): void
|
|
{
|
|
if (!self::canViewInternalCost($adminInfo)) {
|
|
unset($row['internal_cost']);
|
|
}
|
|
}
|
|
|
|
public static function generateOrderNo(): string
|
|
{
|
|
return 'PO' . date('YmdHis') . mt_rand(100000, 999999);
|
|
}
|
|
|
|
private static function normalizeExpressCompany($raw): string
|
|
{
|
|
$ec = strtolower(trim((string) ($raw ?? '')));
|
|
if ($ec === '') {
|
|
return 'auto';
|
|
}
|
|
if (!in_array($ec, ['sf', 'jd', 'jt', 'jtexpress', 'auto'], true)) {
|
|
return 'auto';
|
|
}
|
|
// 统一 jtexpress 为 jt
|
|
if ($ec === 'jtexpress') {
|
|
return 'jt';
|
|
}
|
|
|
|
return $ec;
|
|
}
|
|
|
|
/** 业务订单「处方审核」驳回后,允许医生继续编辑已通过的消费者处方 */
|
|
public static function allowDoctorEditApprovedPrescriptionDueToBusinessReject(int $prescriptionId): bool
|
|
{
|
|
return PrescriptionOrder::where('prescription_id', $prescriptionId)
|
|
->where('prescription_audit_status', 2)
|
|
->whereNull('delete_time')
|
|
->where('fulfillment_status', '<>', 4)
|
|
->count() > 0;
|
|
}
|
|
|
|
/**
|
|
* 医生保存消费者处方后:重置关联业务订单的处方/支付单审核为待审(因处方内容已变)
|
|
*/
|
|
public static function onConsumerPrescriptionSaved(int $prescriptionId): void
|
|
{
|
|
$rows = PrescriptionOrder::where('prescription_id', $prescriptionId)
|
|
->where('prescription_audit_status', 2)
|
|
->whereNull('delete_time')
|
|
->where('fulfillment_status', '<>', 4)
|
|
->select();
|
|
foreach ($rows as $order) {
|
|
$order->prescription_audit_status = 0;
|
|
$order->prescription_audit_remark = '';
|
|
$order->payment_slip_audit_status = 0;
|
|
$order->payment_slip_audit_remark = '';
|
|
self::syncFulfillmentStatus($order);
|
|
$order->save();
|
|
}
|
|
}
|
|
|
|
private static function syncFulfillmentStatus(PrescriptionOrder $order): void
|
|
{
|
|
$fs = (int) $order->fulfillment_status;
|
|
if ($fs === 3 || $fs === 4) {
|
|
return;
|
|
}
|
|
$pa = (int) $order->prescription_audit_status;
|
|
$pay = (int) $order->payment_slip_audit_status;
|
|
if ($pa === 1 && $pay === 1) {
|
|
$order->fulfillment_status = 2;
|
|
} elseif ($pa === 2 || $pay === 2) {
|
|
$order->fulfillment_status = 1;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param mixed $raw
|
|
* @return int[]
|
|
*/
|
|
private static function normalizePayOrderIds($raw): array
|
|
{
|
|
if (!is_array($raw)) {
|
|
return [];
|
|
}
|
|
$ids = array_map('intval', $raw);
|
|
|
|
return array_values(array_unique(array_filter($ids, static fn (int $v): bool => $v > 0)));
|
|
}
|
|
|
|
/**
|
|
* 解除业务订单与支付单的关联(撤回/驳回后支付单可再次被选用)
|
|
*/
|
|
private static function clearPayOrderLinks(PrescriptionOrder $order): void
|
|
{
|
|
PrescriptionOrderPayOrder::where('prescription_order_id', (int) $order->id)->delete();
|
|
$order->linked_pay_order_id = null;
|
|
}
|
|
|
|
/**
|
|
* 支付单不可同时关联多条「有效」业务订单(未删除且未撤回/取消);$exceptPrescriptionOrderId 为当前编辑单 ID 时跳过自检
|
|
*
|
|
* @param int[] $payOrderIds
|
|
*/
|
|
private static function assertPayOrdersExclusive(array $payOrderIds, ?int $exceptPrescriptionOrderId): ?string
|
|
{
|
|
$ids = array_values(array_unique(array_filter(array_map('intval', $payOrderIds), static fn (int $v): bool => $v > 0)));
|
|
if ($ids === []) {
|
|
return null;
|
|
}
|
|
$activePoIds = PrescriptionOrder::whereNull('delete_time')
|
|
->where('fulfillment_status', '<>', 4)
|
|
->column('id');
|
|
if ($activePoIds === []) {
|
|
return null;
|
|
}
|
|
$activeSet = array_fill_keys(array_map('intval', $activePoIds), true);
|
|
$links = PrescriptionOrderPayOrder::whereIn('pay_order_id', $ids)->select();
|
|
foreach ($links as $link) {
|
|
$poId = (int) $link->prescription_order_id;
|
|
if ($exceptPrescriptionOrderId !== null && $poId === $exceptPrescriptionOrderId) {
|
|
continue;
|
|
}
|
|
if (!isset($activeSet[$poId])) {
|
|
continue;
|
|
}
|
|
|
|
return '支付单 #' . (int) $link->pay_order_id . ' 已关联其他有效业务订单,不可重复关联';
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* @param int[] $payOrderIds
|
|
*/
|
|
private static function replacePayOrderLinks(int $prescriptionOrderId, array $payOrderIds): void
|
|
{
|
|
PrescriptionOrderPayOrder::where('prescription_order_id', $prescriptionOrderId)->delete();
|
|
$t = time();
|
|
foreach ($payOrderIds as $pid) {
|
|
$link = new PrescriptionOrderPayOrder();
|
|
$link->prescription_order_id = $prescriptionOrderId;
|
|
$link->pay_order_id = $pid;
|
|
$link->create_time = $t;
|
|
$link->save();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return int[]
|
|
*/
|
|
private static function linkedPayOrderIdList(int $prescriptionOrderId): array
|
|
{
|
|
return array_map(
|
|
'intval',
|
|
PrescriptionOrderPayOrder::where('prescription_order_id', $prescriptionOrderId)->order('id', 'asc')->column('pay_order_id')
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @return array<int, array<string, mixed>>
|
|
*/
|
|
private static function linkedPayOrdersPayload(array $ids): array
|
|
{
|
|
if ($ids === []) {
|
|
return [];
|
|
}
|
|
$rows = Order::whereIn('id', $ids)->whereNull('delete_time')
|
|
->field(['id', 'order_no', 'order_type', 'amount', 'status', 'create_time', 'creator_id', 'remark'])
|
|
->order('id', 'asc')
|
|
->select()
|
|
->toArray();
|
|
|
|
return $rows;
|
|
}
|
|
|
|
/**
|
|
* @param array<string,mixed> $arr
|
|
*/
|
|
private static function attachLinkedPayOrders(array &$arr): void
|
|
{
|
|
$id = (int) ($arr['id'] ?? 0);
|
|
if ($id <= 0) {
|
|
$arr['pay_order_ids'] = [];
|
|
$arr['linked_pay_orders'] = [];
|
|
|
|
return;
|
|
}
|
|
$ids = self::linkedPayOrderIdList($id);
|
|
$arr['pay_order_ids'] = $ids;
|
|
$arr['linked_pay_orders'] = self::linkedPayOrdersPayload($ids);
|
|
}
|
|
|
|
/**
|
|
* @param array<string,mixed> $params
|
|
* @return array<string,mixed>|false
|
|
*/
|
|
public static function create(array $params, int $adminId, array $adminInfo)
|
|
{
|
|
self::$error = '';
|
|
$rxId = (int) $params['prescription_id'];
|
|
$diagId = (int) $params['diagnosis_id'];
|
|
$payOrderIds = self::normalizePayOrderIds($params['pay_order_ids'] ?? []);
|
|
|
|
$rx = PrescriptionLogic::detail($rxId, $adminId, $adminInfo);
|
|
if ($rx === null) {
|
|
$err = PrescriptionLogic::getError();
|
|
|
|
self::$error = $err !== '' ? $err : '处方不存在';
|
|
|
|
return false;
|
|
}
|
|
if ((int) ($rx['diagnosis_id'] ?? 0) !== $diagId) {
|
|
self::$error = '诊单与处方不匹配';
|
|
|
|
return false;
|
|
}
|
|
|
|
if (PrescriptionOrder::where('prescription_id', $rxId)->whereNull('delete_time')->where('fulfillment_status', '<>', 4)->count() > 0) {
|
|
self::$error = '该处方已存在有效业务订单(未撤回前不可重复创建)';
|
|
|
|
return false;
|
|
}
|
|
|
|
$diag = Diagnosis::where('id', $diagId)->whereNull('delete_time')->find();
|
|
if (!$diag) {
|
|
self::$error = '诊单不存在';
|
|
|
|
return false;
|
|
}
|
|
|
|
if ($payOrderIds !== []) {
|
|
$linkErr = OrderLogic::assertPayOrdersLinkable($payOrderIds, $diagId, $adminId, $adminInfo);
|
|
if ($linkErr !== null) {
|
|
self::$error = $linkErr;
|
|
|
|
return false;
|
|
}
|
|
$exErr = self::assertPayOrdersExclusive($payOrderIds, null);
|
|
if ($exErr !== null) {
|
|
self::$error = $exErr;
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
$internalCost = null;
|
|
if (isset($params['internal_cost']) && $params['internal_cost'] !== '' && $params['internal_cost'] !== null) {
|
|
if (self::canViewInternalCost($adminInfo)) {
|
|
$internalCost = round((float) $params['internal_cost'], 2);
|
|
}
|
|
}
|
|
|
|
$medDays = $params['medication_days'] ?? null;
|
|
$medDays = $medDays === '' || $medDays === null ? null : (int) $medDays;
|
|
|
|
$order = new PrescriptionOrder();
|
|
$order->order_no = self::generateOrderNo();
|
|
$order->prescription_id = $rxId;
|
|
$order->diagnosis_id = $diagId;
|
|
$order->creator_id = $adminId;
|
|
$order->recipient_name = (string) $params['recipient_name'];
|
|
$order->recipient_phone = (string) $params['recipient_phone'];
|
|
$order->shipping_address = (string) $params['shipping_address'];
|
|
$order->is_follow_up = (int) ($params['is_follow_up'] ?? 0) === 1 ? 1 : 0;
|
|
$order->medication_days = $medDays > 0 ? $medDays : null;
|
|
$order->prev_staff = (string) ($params['prev_staff'] ?? '');
|
|
$order->service_channel = (string) ($params['service_channel'] ?? '');
|
|
$order->service_package = (string) ($params['service_package'] ?? '');
|
|
$order->tracking_number = (string) ($params['tracking_number'] ?? '');
|
|
$order->express_company = self::normalizeExpressCompany($params['express_company'] ?? 'auto');
|
|
$order->fee_type = (int) $params['fee_type'];
|
|
$order->amount = round((float) $params['amount'], 2);
|
|
$order->internal_cost = $internalCost;
|
|
$order->remark_extra = (string) ($params['remark_extra'] ?? '');
|
|
$order->linked_pay_order_id = $payOrderIds !== [] ? $payOrderIds[0] : null;
|
|
$order->prescription_audit_status = 0;
|
|
$order->prescription_audit_remark = '';
|
|
$order->payment_slip_audit_status = 0;
|
|
$order->payment_slip_audit_remark = '';
|
|
$order->fulfillment_status = 1;
|
|
|
|
try {
|
|
$order->save();
|
|
} catch (\Throwable $e) {
|
|
self::$error = $e->getMessage();
|
|
|
|
return false;
|
|
}
|
|
|
|
if ($payOrderIds !== []) {
|
|
self::replacePayOrderLinks((int) $order->id, $payOrderIds);
|
|
}
|
|
|
|
$out = $order->toArray();
|
|
self::maskInternalCostIfNeeded($out, $adminInfo);
|
|
self::attachLinkedPayOrders($out);
|
|
|
|
return $out;
|
|
}
|
|
|
|
public static function detail(int $id, int $adminId, array $adminInfo): ?array
|
|
{
|
|
self::$error = '';
|
|
$row = PrescriptionOrder::where('id', $id)->whereNull('delete_time')->find();
|
|
if (!$row) {
|
|
self::$error = '订单不存在';
|
|
|
|
return null;
|
|
}
|
|
if (!self::canAccessOrder($row, $adminId, $adminInfo)) {
|
|
self::$error = '无权限查看';
|
|
|
|
return null;
|
|
}
|
|
$arr = $row->toArray();
|
|
self::maskInternalCostIfNeeded($arr, $adminInfo);
|
|
self::attachLinkedPayOrders($arr);
|
|
|
|
return $arr;
|
|
}
|
|
|
|
/**
|
|
* 物流轨迹(顺丰/京东等,优先快递100;未配置密钥时返回官网链接)
|
|
*
|
|
* @return array<string,mixed>|null
|
|
*/
|
|
public static function logisticsTrace(int $id, string $expressCompanyOverride, int $adminId, array $adminInfo): ?array
|
|
{
|
|
self::$error = '';
|
|
$row = PrescriptionOrder::where('id', $id)->whereNull('delete_time')->find();
|
|
if (!$row) {
|
|
self::$error = '订单不存在';
|
|
|
|
return null;
|
|
}
|
|
if (!self::canAccessOrder($row, $adminId, $adminInfo)) {
|
|
self::$error = '无权限查看';
|
|
|
|
return null;
|
|
}
|
|
$num = trim((string) ($row->tracking_number ?? ''));
|
|
if ($num === '') {
|
|
self::$error = '未填写快递单号';
|
|
|
|
return null;
|
|
}
|
|
$ec = trim($expressCompanyOverride) !== '' ? self::normalizeExpressCompany($expressCompanyOverride) : self::normalizeExpressCompany($row->express_company ?? 'auto');
|
|
|
|
// 优先从数据库查询物流追踪信息
|
|
$trackingData = \app\common\service\ExpressTrackingService::getDetailByTrackingNumber($num);
|
|
|
|
if ($trackingData && !empty($trackingData['traces'])) {
|
|
// 从数据库获取到数据,直接返回
|
|
$payload = [
|
|
'carrier' => $trackingData['express_company'],
|
|
'carrier_label' => $trackingData['express_company_name'],
|
|
'kuaidi_com' => $trackingData['express_company'],
|
|
'traces' => array_map(function($trace) {
|
|
return [
|
|
'time' => $trace['trace_time'],
|
|
'ftime' => $trace['trace_time'],
|
|
'context' => $trace['trace_context'],
|
|
'location' => $trace['location'],
|
|
'status' => $trace['status'],
|
|
'statusCode' => $trace['status_code'],
|
|
];
|
|
}, $trackingData['traces']),
|
|
'state' => $trackingData['current_state'],
|
|
'state_text' => $trackingData['current_state_text'],
|
|
'source' => 'database',
|
|
'hint' => '',
|
|
'official_url' => '',
|
|
'last_query_time' => date('Y-m-d H:i:s', $trackingData['last_query_time']),
|
|
'query_count' => $trackingData['query_count'],
|
|
];
|
|
} else {
|
|
// 数据库没有数据,调用快递100 API
|
|
$payload = ExpressTrackService::query($ec, $num, (string) ($row->recipient_phone ?? ''));
|
|
$payload['source'] = 'api';
|
|
}
|
|
|
|
$payload['official_urls'] = ExpressTrackService::officialUrls($num);
|
|
$payload['tracking_number'] = $num;
|
|
$payload['express_company_used'] = $ec;
|
|
|
|
return $payload;
|
|
}
|
|
|
|
/**
|
|
* @param array<string,mixed> $params
|
|
* @return array<string,mixed>|false
|
|
*/
|
|
public static function edit(array $params, int $adminId, array $adminInfo)
|
|
{
|
|
self::$error = '';
|
|
$id = (int) $params['id'];
|
|
$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;
|
|
}
|
|
$fs = (int) $order->fulfillment_status;
|
|
if ($fs === 3 || $fs === 4) {
|
|
self::$error = '已完成或已取消的订单不可编辑';
|
|
|
|
return false;
|
|
}
|
|
|
|
$medDays = $params['medication_days'] ?? null;
|
|
$medDays = $medDays === '' || $medDays === null ? null : (int) $medDays;
|
|
|
|
$order->recipient_name = (string) $params['recipient_name'];
|
|
$order->recipient_phone = (string) $params['recipient_phone'];
|
|
$order->shipping_address = (string) $params['shipping_address'];
|
|
$order->is_follow_up = (int) ($params['is_follow_up'] ?? 0) === 1 ? 1 : 0;
|
|
$order->medication_days = $medDays > 0 ? $medDays : null;
|
|
$order->prev_staff = (string) ($params['prev_staff'] ?? '');
|
|
$order->service_channel = (string) ($params['service_channel'] ?? '');
|
|
$order->service_package = (string) ($params['service_package'] ?? '');
|
|
$order->tracking_number = (string) ($params['tracking_number'] ?? '');
|
|
if (array_key_exists('express_company', $params)) {
|
|
$order->express_company = self::normalizeExpressCompany($params['express_company']);
|
|
}
|
|
$order->fee_type = (int) $params['fee_type'];
|
|
$order->amount = round((float) $params['amount'], 2);
|
|
$order->remark_extra = (string) ($params['remark_extra'] ?? '');
|
|
|
|
$diagId = (int) $order->diagnosis_id;
|
|
|
|
if (array_key_exists('pay_order_ids', $params)) {
|
|
$payOrderIds = self::normalizePayOrderIds($params['pay_order_ids']);
|
|
$linkErr = OrderLogic::assertPayOrdersLinkable($payOrderIds, $diagId, $adminId, $adminInfo);
|
|
if ($linkErr !== null) {
|
|
self::$error = $linkErr;
|
|
|
|
return false;
|
|
}
|
|
$exErr = self::assertPayOrdersExclusive($payOrderIds, (int) $order->id);
|
|
if ($exErr !== null) {
|
|
self::$error = $exErr;
|
|
|
|
return false;
|
|
}
|
|
self::replacePayOrderLinks((int) $order->id, $payOrderIds);
|
|
$order->linked_pay_order_id = $payOrderIds !== [] ? $payOrderIds[0] : null;
|
|
} elseif (array_key_exists('linked_pay_order_id', $params)) {
|
|
$lp = $params['linked_pay_order_id'];
|
|
if ($lp === '' || $lp === null || (int) $lp <= 0) {
|
|
self::replacePayOrderLinks((int) $order->id, []);
|
|
$order->linked_pay_order_id = null;
|
|
} else {
|
|
$single = [(int) $lp];
|
|
$linkErr = OrderLogic::assertPayOrdersLinkable($single, $diagId, $adminId, $adminInfo);
|
|
if ($linkErr !== null) {
|
|
self::$error = $linkErr;
|
|
|
|
return false;
|
|
}
|
|
$exErr = self::assertPayOrdersExclusive($single, (int) $order->id);
|
|
if ($exErr !== null) {
|
|
self::$error = $exErr;
|
|
|
|
return false;
|
|
}
|
|
self::replacePayOrderLinks((int) $order->id, $single);
|
|
$order->linked_pay_order_id = $single[0];
|
|
}
|
|
}
|
|
|
|
if (array_key_exists('internal_cost', $params) && self::canViewInternalCost($adminInfo)) {
|
|
$raw = $params['internal_cost'];
|
|
if ($raw === '' || $raw === null) {
|
|
$order->internal_cost = null;
|
|
} else {
|
|
$order->internal_cost = round((float) $raw, 2);
|
|
}
|
|
}
|
|
|
|
try {
|
|
$order->save();
|
|
} catch (\Throwable $e) {
|
|
self::$error = $e->getMessage();
|
|
|
|
return false;
|
|
}
|
|
|
|
$out = $order->toArray();
|
|
self::maskInternalCostIfNeeded($out, $adminInfo);
|
|
self::attachLinkedPayOrders($out);
|
|
|
|
return $out;
|
|
}
|
|
|
|
/**
|
|
* @return array<string,mixed>|false
|
|
*/
|
|
public static function withdraw(int $id, int $adminId, array $adminInfo)
|
|
{
|
|
self::$error = '';
|
|
$order = PrescriptionOrder::where('id', $id)->whereNull('delete_time')->find();
|
|
if (!$order) {
|
|
self::$error = '订单不存在';
|
|
|
|
return false;
|
|
}
|
|
if (!self::canWithdrawOrder($order, $adminId, $adminInfo)) {
|
|
self::$error = '无权限撤回';
|
|
|
|
return false;
|
|
}
|
|
if ((int) $order->fulfillment_status !== 1) {
|
|
self::$error = '仅「待双审通过」状态可撤回;双审通过后请走履约/完成流程';
|
|
|
|
return false;
|
|
}
|
|
|
|
$order->fulfillment_status = 4;
|
|
self::clearPayOrderLinks($order);
|
|
|
|
try {
|
|
$order->save();
|
|
} catch (\Throwable $e) {
|
|
self::$error = $e->getMessage();
|
|
|
|
return false;
|
|
}
|
|
|
|
$out = $order->toArray();
|
|
self::maskInternalCostIfNeeded($out, $adminInfo);
|
|
self::attachLinkedPayOrders($out);
|
|
|
|
return $out;
|
|
}
|
|
|
|
/**
|
|
* @return array<string,mixed>|false
|
|
*/
|
|
public static function auditPrescription(int $id, string $action, string $remark, int $adminId, array $adminInfo)
|
|
{
|
|
self::$error = '';
|
|
$order = PrescriptionOrder::where('id', $id)->whereNull('delete_time')->find();
|
|
if (!$order) {
|
|
self::$error = '订单不存在';
|
|
|
|
return false;
|
|
}
|
|
if (!self::canAuditPrescriptionOrder($adminInfo)) {
|
|
self::$error = '无处方审核权限';
|
|
|
|
return false;
|
|
}
|
|
if ((int) $order->prescription_audit_status !== 0) {
|
|
self::$error = '当前无需处方审核';
|
|
|
|
return false;
|
|
}
|
|
$fs = (int) $order->fulfillment_status;
|
|
if ($fs === 3 || $fs === 4) {
|
|
self::$error = '订单已结束';
|
|
|
|
return false;
|
|
}
|
|
|
|
if ($action === 'reject' && trim($remark) === '') {
|
|
self::$error = '驳回时请填写审核意见';
|
|
|
|
return false;
|
|
}
|
|
|
|
if ($action === 'approve') {
|
|
$order->prescription_audit_status = 1;
|
|
$order->prescription_audit_remark = mb_substr(trim($remark), 0, 500);
|
|
} else {
|
|
$order->prescription_audit_status = 2;
|
|
$order->prescription_audit_remark = mb_substr(trim($remark), 0, 500);
|
|
$order->payment_slip_audit_status = 0;
|
|
$order->payment_slip_audit_remark = '';
|
|
}
|
|
self::syncFulfillmentStatus($order);
|
|
if ($action === 'reject') {
|
|
self::clearPayOrderLinks($order);
|
|
}
|
|
|
|
try {
|
|
$order->save();
|
|
} catch (\Throwable $e) {
|
|
self::$error = $e->getMessage();
|
|
|
|
return false;
|
|
}
|
|
|
|
$out = $order->toArray();
|
|
self::maskInternalCostIfNeeded($out, $adminInfo);
|
|
self::attachLinkedPayOrders($out);
|
|
|
|
return $out;
|
|
}
|
|
|
|
/**
|
|
* @return array<string,mixed>|false
|
|
*/
|
|
public static function auditPaymentSlip(int $id, string $action, string $remark, int $adminId, array $adminInfo)
|
|
{
|
|
self::$error = '';
|
|
$order = PrescriptionOrder::where('id', $id)->whereNull('delete_time')->find();
|
|
if (!$order) {
|
|
self::$error = '订单不存在';
|
|
|
|
return false;
|
|
}
|
|
if (!self::canAuditPaymentSlipOrder($adminInfo)) {
|
|
self::$error = '无支付单审核权限';
|
|
|
|
return false;
|
|
}
|
|
if ((int) $order->prescription_audit_status !== 1) {
|
|
self::$error = '请先通过处方审核';
|
|
|
|
return false;
|
|
}
|
|
if ((int) $order->payment_slip_audit_status !== 0) {
|
|
self::$error = '当前无需支付单审核';
|
|
|
|
return false;
|
|
}
|
|
$fs = (int) $order->fulfillment_status;
|
|
if ($fs === 3 || $fs === 4) {
|
|
self::$error = '订单已结束';
|
|
|
|
return false;
|
|
}
|
|
|
|
if ($action === 'reject' && trim($remark) === '') {
|
|
self::$error = '驳回时请填写审核意见';
|
|
|
|
return false;
|
|
}
|
|
|
|
if ($action === 'approve') {
|
|
$order->payment_slip_audit_status = 1;
|
|
$order->payment_slip_audit_remark = mb_substr(trim($remark), 0, 500);
|
|
} else {
|
|
$order->payment_slip_audit_status = 2;
|
|
$order->payment_slip_audit_remark = mb_substr(trim($remark), 0, 500);
|
|
}
|
|
self::syncFulfillmentStatus($order);
|
|
if ($action === 'reject') {
|
|
self::clearPayOrderLinks($order);
|
|
}
|
|
|
|
try {
|
|
$order->save();
|
|
} catch (\Throwable $e) {
|
|
self::$error = $e->getMessage();
|
|
|
|
return false;
|
|
}
|
|
|
|
$out = $order->toArray();
|
|
self::maskInternalCostIfNeeded($out, $adminInfo);
|
|
self::attachLinkedPayOrders($out);
|
|
|
|
return $out;
|
|
}
|
|
}
|