493 lines
17 KiB
PHP
Executable File
493 lines
17 KiB
PHP
Executable File
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace app\adminapi\controller\tcm;
|
||
|
||
use app\adminapi\controller\BaseAdminController;
|
||
use app\adminapi\lists\tcm\PrescriptionOrderLists;
|
||
use app\adminapi\logic\order\OrderLogic;
|
||
use app\adminapi\logic\tcm\PrescriptionOrderLogic;
|
||
use app\adminapi\validate\tcm\PrescriptionOrderValidate;
|
||
|
||
/**
|
||
* 处方业务订单(非支付单)
|
||
*/
|
||
class PrescriptionOrderController extends BaseAdminController
|
||
{
|
||
public function lists()
|
||
{
|
||
return $this->dataLists(new PrescriptionOrderLists());
|
||
}
|
||
|
||
/**
|
||
* 处方业务订单导出(与 lists 相同筛选条件,Excel;参数 export=1 预估 export=2 下载)
|
||
*/
|
||
public function export()
|
||
{
|
||
return $this->dataLists(new PrescriptionOrderLists());
|
||
}
|
||
|
||
/**
|
||
* 指定诊单下可关联的支付单(待支付/已支付,创建/编辑业务订单时多选关联)
|
||
*/
|
||
public function paidPayOrders()
|
||
{
|
||
$params = (new PrescriptionOrderValidate())->get()->goCheck('paidPayOrders');
|
||
$exceptPo = (int) $this->request->get('prescription_order_id', 0);
|
||
|
||
$lists = OrderLogic::listPaidOrdersForDiagnosis(
|
||
(int) $params['diagnosis_id'],
|
||
$this->adminId,
|
||
$this->adminInfo,
|
||
$exceptPo > 0 ? $exceptPo : null
|
||
);
|
||
|
||
$min = PrescriptionOrderLogic::depositMinAmount();
|
||
|
||
// if ($min > 0) {
|
||
// $lists = array_values(array_filter(
|
||
// $lists,
|
||
// static fn(array $r): bool => round((float) ($r['amount'] ?? 0), 2) >= $min
|
||
// ));
|
||
// }
|
||
|
||
return $this->success('', [
|
||
'lists' => $lists,
|
||
'deposit_min_amount' => $min,
|
||
]);
|
||
}
|
||
|
||
public function create()
|
||
{
|
||
$params = (new PrescriptionOrderValidate())->post()->goCheck('create');
|
||
$result = PrescriptionOrderLogic::create($params, $this->adminId, $this->adminInfo);
|
||
if ($result === false) {
|
||
return $this->fail(PrescriptionOrderLogic::getError());
|
||
}
|
||
|
||
return $this->success('创建成功', $result);
|
||
}
|
||
|
||
public function detail()
|
||
{
|
||
$params = (new PrescriptionOrderValidate())->get()->goCheck('detail');
|
||
$detail = PrescriptionOrderLogic::detail((int) $params['id'], $this->adminId, $this->adminInfo);
|
||
if ($detail === null) {
|
||
return $this->fail(PrescriptionOrderLogic::getError());
|
||
}
|
||
|
||
return $this->data($detail);
|
||
}
|
||
|
||
/**
|
||
* 快递轨迹查询(对接快递100;未配置时仍可跳转顺丰/京东官网)
|
||
*/
|
||
public function logisticsTrace()
|
||
{
|
||
$params = (new PrescriptionOrderValidate())->get()->goCheck('logisticsTrace');
|
||
$expressOverride = trim((string) $this->request->get('express_company', ''));
|
||
$phoneTail = trim((string) ($params['phone_tail'] ?? ''));
|
||
$data = PrescriptionOrderLogic::logisticsTrace(
|
||
(int) $params['id'],
|
||
$expressOverride,
|
||
$this->adminId,
|
||
$this->adminInfo,
|
||
$phoneTail
|
||
);
|
||
if ($data === null) {
|
||
return $this->fail(PrescriptionOrderLogic::getError());
|
||
}
|
||
|
||
return $this->success('', $data);
|
||
}
|
||
|
||
/**
|
||
* 直接调用京东官方物流接口刷新轨迹并落库(绕过快递100缓存)
|
||
*/
|
||
public function logisticsJdUpdate()
|
||
{
|
||
$params = (new PrescriptionOrderValidate())->post()->goCheck('logisticsJdUpdate');
|
||
$data = PrescriptionOrderLogic::logisticsJdUpdate(
|
||
(int) $params['id'],
|
||
$this->adminId,
|
||
$this->adminInfo
|
||
);
|
||
if ($data === null) {
|
||
return $this->fail(PrescriptionOrderLogic::getError());
|
||
}
|
||
|
||
return $this->success((string) ($data['message'] ?? '京东物流轨迹已更新'), $data);
|
||
}
|
||
|
||
public function edit()
|
||
{
|
||
$params = (new PrescriptionOrderValidate())->post()->goCheck('edit');
|
||
$result = PrescriptionOrderLogic::edit($params, $this->adminId, $this->adminInfo);
|
||
if ($result === false) {
|
||
return $this->fail(PrescriptionOrderLogic::getError());
|
||
}
|
||
|
||
return $this->success('保存成功', $result);
|
||
}
|
||
|
||
public function updateAmount()
|
||
{
|
||
$params = (new PrescriptionOrderValidate())->post()->goCheck('updateAmount');
|
||
$result = PrescriptionOrderLogic::updateAmount($params, $this->adminId, $this->adminInfo);
|
||
if ($result === false) {
|
||
return $this->fail(PrescriptionOrderLogic::getError());
|
||
}
|
||
|
||
return $this->success('修改成功');
|
||
}
|
||
|
||
/**
|
||
* 设置发货类型(甘草 / 洛阳)
|
||
*/
|
||
public function setShipMode()
|
||
{
|
||
$params = (new PrescriptionOrderValidate())->post()->goCheck('setShipMode');
|
||
$result = PrescriptionOrderLogic::setShipMode(
|
||
(int) $params['id'],
|
||
(string) ($params['ship_mode'] ?? 'gancao'),
|
||
$this->adminId,
|
||
$this->adminInfo
|
||
);
|
||
if ($result === false) {
|
||
return $this->fail(PrescriptionOrderLogic::getError());
|
||
}
|
||
|
||
return $this->success('已保存', $result);
|
||
}
|
||
|
||
/**
|
||
* 修改关联处方的患者姓名与手机号(订单详情场景)
|
||
*/
|
||
public function patchPrescriptionPatient()
|
||
{
|
||
$params = (new PrescriptionOrderValidate())->post()->goCheck('patchPrescriptionPatient');
|
||
$ok = PrescriptionOrderLogic::patchPrescriptionPatient(
|
||
(int) $params['id'],
|
||
(string) $params['patient_name'],
|
||
(string) $params['phone'],
|
||
$this->adminId,
|
||
$this->adminInfo
|
||
);
|
||
if (!$ok) {
|
||
return $this->fail(PrescriptionOrderLogic::getError());
|
||
}
|
||
|
||
return $this->success('保存成功');
|
||
}
|
||
|
||
public function auditPrescription()
|
||
{
|
||
$params = (new PrescriptionOrderValidate())->post()->goCheck('auditPrescription');
|
||
$result = PrescriptionOrderLogic::auditPrescription(
|
||
(int) $params['id'],
|
||
(string) $params['action'],
|
||
(string) ($params['remark'] ?? ''),
|
||
$this->adminId,
|
||
$this->adminInfo
|
||
);
|
||
if ($result === false) {
|
||
return $this->fail(PrescriptionOrderLogic::getError());
|
||
}
|
||
|
||
return $this->success('操作成功', $result);
|
||
}
|
||
|
||
/**
|
||
* 撤回处方审核
|
||
*/
|
||
public function revokeRxAudit()
|
||
{
|
||
$params = (new PrescriptionOrderValidate())->post()->goCheck('detail');
|
||
$result = PrescriptionOrderLogic::revokeRxAudit(
|
||
(int) $params['id'],
|
||
$this->adminId,
|
||
$this->adminInfo
|
||
);
|
||
if ($result === false) {
|
||
return $this->fail(PrescriptionOrderLogic::getError());
|
||
}
|
||
|
||
return $this->success('处方审核已撤回', $result);
|
||
}
|
||
|
||
public function auditPayment()
|
||
{
|
||
$params = (new PrescriptionOrderValidate())->post()->goCheck('auditPayment');
|
||
$result = PrescriptionOrderLogic::auditPaymentSlip(
|
||
(int) $params['id'],
|
||
(string) $params['action'],
|
||
(string) ($params['remark'] ?? ''),
|
||
$this->adminId,
|
||
$this->adminInfo
|
||
);
|
||
if ($result === false) {
|
||
return $this->fail(PrescriptionOrderLogic::getError());
|
||
}
|
||
|
||
return $this->success('操作成功', $result);
|
||
}
|
||
|
||
/**
|
||
* 撤回支付单审核
|
||
*/
|
||
public function revokePayAudit()
|
||
{
|
||
$params = (new PrescriptionOrderValidate())->post()->goCheck('detail');
|
||
$result = PrescriptionOrderLogic::revokePayAudit(
|
||
(int) $params['id'],
|
||
$this->adminId,
|
||
$this->adminInfo
|
||
);
|
||
if ($result === false) {
|
||
return $this->fail(PrescriptionOrderLogic::getError());
|
||
}
|
||
|
||
return $this->success('支付单审核已撤回', $result);
|
||
}
|
||
|
||
/**
|
||
* 确认发货:将履约状态推进到 5(已发货),同时更新快递信息
|
||
*/
|
||
public function ship()
|
||
{
|
||
$params = (new PrescriptionOrderValidate())->post()->goCheck('ship');
|
||
$result = PrescriptionOrderLogic::ship(
|
||
(int) $params['id'],
|
||
(string) ($params['express_company'] ?? 'auto'),
|
||
(string) ($params['tracking_number'] ?? ''),
|
||
(string) ($params['ship_mode'] ?? 'gancao'),
|
||
$this->adminId,
|
||
$this->adminInfo
|
||
);
|
||
if ($result === false) {
|
||
return $this->fail(PrescriptionOrderLogic::getError());
|
||
}
|
||
|
||
return $this->success('发货成功', $result);
|
||
}
|
||
|
||
/**
|
||
* 医助/创建人撤回:仅「待双审通过」可撤(未通过或双审均驳回等仍为该状态)
|
||
*/
|
||
public function withdraw()
|
||
{
|
||
$params = (new PrescriptionOrderValidate())->post()->goCheck('withdraw');
|
||
$result = PrescriptionOrderLogic::withdraw((int) $params['id'], $this->adminId, $this->adminInfo);
|
||
if ($result === false) {
|
||
return $this->fail(PrescriptionOrderLogic::getError());
|
||
}
|
||
|
||
return $this->success('已撤回', $result);
|
||
}
|
||
|
||
/**
|
||
* @notes 批量将处方业务订单改派给其他医助(写入 creator_id 并逐单记操作日志)
|
||
*/
|
||
public function batchAssignAssistant()
|
||
{
|
||
if (!PrescriptionOrderLogic::canSeeAllPrescriptionOrders($this->adminInfo)) {
|
||
return $this->fail('无权限批量改派订单');
|
||
}
|
||
$params = $this->request->post();
|
||
$rawIds = $params['order_ids'] ?? [];
|
||
if (!\is_array($rawIds) || $rawIds === []) {
|
||
return $this->fail('请选择订单');
|
||
}
|
||
$assistantId = (int) ($params['assistant_id'] ?? 0);
|
||
$result = PrescriptionOrderLogic::batchAssignAssistant($rawIds, $assistantId, $this->adminId, $this->adminInfo);
|
||
if ($result === false) {
|
||
return $this->fail(PrescriptionOrderLogic::getError());
|
||
}
|
||
$msg = '已改派 ' . (int) $result['success'] . ' 单';
|
||
if (!empty($result['errors'])) {
|
||
$msg .= ';' . implode(';', $result['errors']);
|
||
}
|
||
|
||
return $this->success($msg, $result);
|
||
}
|
||
|
||
/**
|
||
* 获取业务订单操作日志
|
||
*/
|
||
public function logs()
|
||
{
|
||
$params = (new PrescriptionOrderValidate())->get()->goCheck('logs');
|
||
$result = PrescriptionOrderLogic::getLogs((int) $params['id'], $this->adminId, $this->adminInfo);
|
||
|
||
// 遇到没有权限或者订单不存在,逻辑里设置了 self::$error
|
||
if ($result === [] && PrescriptionOrderLogic::getError() !== '') {
|
||
return $this->fail(PrescriptionOrderLogic::getError());
|
||
}
|
||
|
||
return $this->success('', $result);
|
||
}
|
||
|
||
/**
|
||
* 手工新增操作日志(可选同步调整处方/支付单审核状态)
|
||
*/
|
||
public function addLog()
|
||
{
|
||
$params = (new PrescriptionOrderValidate())->post()->goCheck('addLog');
|
||
$result = PrescriptionOrderLogic::addLog($params, $this->adminId, $this->adminInfo);
|
||
if ($result === false) {
|
||
return $this->fail(PrescriptionOrderLogic::getError());
|
||
}
|
||
|
||
return $this->success('日志已添加', $result);
|
||
}
|
||
|
||
/**
|
||
* 为「已发货」订单新增一条关联支付单,并重置支付单审核状态为待审核
|
||
*/
|
||
public function addPayOrder()
|
||
{
|
||
$params = (new PrescriptionOrderValidate())->post()->goCheck('addPayOrder');
|
||
$result = PrescriptionOrderLogic::addPayOrder($params, $this->adminId, $this->adminInfo);
|
||
if ($result === false) {
|
||
return $this->fail(PrescriptionOrderLogic::getError());
|
||
}
|
||
|
||
return $this->success('新增支付单成功', $result);
|
||
}
|
||
|
||
/**
|
||
* 为「已发货」订单关联已有支付单,并重置支付单审核状态为待审核
|
||
*/
|
||
public function linkPayOrder()
|
||
{
|
||
$params = (new PrescriptionOrderValidate())->post()->goCheck('linkPayOrder');
|
||
$result = PrescriptionOrderLogic::linkPayOrder($params, $this->adminId, $this->adminInfo);
|
||
if ($result === false) {
|
||
return $this->fail(PrescriptionOrderLogic::getError());
|
||
}
|
||
|
||
return $this->success('关联支付单成功', $result);
|
||
}
|
||
|
||
/**
|
||
* 已发货/已签收:仅提交完单申请(不新增/关联支付单),并重置支付审核为待审核
|
||
*/
|
||
public function requestCompletion()
|
||
{
|
||
$params = (new PrescriptionOrderValidate())->post()->goCheck('requestCompletion');
|
||
$result = PrescriptionOrderLogic::requestCompletion($params, $this->adminId, $this->adminInfo);
|
||
if ($result === false) {
|
||
return $this->fail(PrescriptionOrderLogic::getError());
|
||
}
|
||
|
||
return $this->success('完单申请已提交', $result);
|
||
}
|
||
|
||
/**
|
||
* 将「已发货」且支付审核已通过的订单标记为「已完成」
|
||
*/
|
||
public function complete()
|
||
{
|
||
$params = (new PrescriptionOrderValidate())->post()->goCheck('complete');
|
||
$result = PrescriptionOrderLogic::complete(
|
||
(int) $params['id'],
|
||
$this->adminId,
|
||
$this->adminInfo,
|
||
(int) $params['fulfillment_status']
|
||
);
|
||
if ($result === false) {
|
||
return $this->fail(PrescriptionOrderLogic::getError());
|
||
}
|
||
|
||
return $this->success('操作成功', $result);
|
||
}
|
||
|
||
/**
|
||
* 业务订单退款(须填写原因;关联收款单标记已退款)
|
||
*/
|
||
public function refund()
|
||
{
|
||
$params = (new PrescriptionOrderValidate())->post()->goCheck('refund');
|
||
$rawRefundAmount = $params['refund_amount'] ?? null;
|
||
$refundAmount = ($rawRefundAmount === null || $rawRefundAmount === '')
|
||
? null
|
||
: round((float) $rawRefundAmount, 2);
|
||
|
||
$result = PrescriptionOrderLogic::refund(
|
||
(int) $params['id'],
|
||
(string) ($params['reason'] ?? ''),
|
||
$this->adminId,
|
||
$this->adminInfo,
|
||
$refundAmount
|
||
);
|
||
if ($result === false) {
|
||
return $this->fail(PrescriptionOrderLogic::getError());
|
||
}
|
||
|
||
return $this->success('退款成功', $result);
|
||
}
|
||
|
||
/**
|
||
* 甘草药管家:处方下单(CTM_PREVIEW → CTM_SUBMIT_RECIPEL)
|
||
*
|
||
* @see https://apidoc.igancao.com/service-doc/scm-outer-recipel.html
|
||
*/
|
||
public function submitGancaoRecipel()
|
||
{
|
||
try {
|
||
$params = (new PrescriptionOrderValidate())->post()->goCheck('submitGancaoRecipel');
|
||
$result = PrescriptionOrderLogic::submitGancaoRecipel((int) $params['id'], $this->adminId, $this->adminInfo);
|
||
|
||
if ($result === false) {
|
||
$error = PrescriptionOrderLogic::getError();
|
||
\think\facade\Log::error('submitGancaoRecipel failed', ['error' => $error, 'params' => $params]);
|
||
return $this->fail($error);
|
||
}
|
||
|
||
// 确保返回的数据是可序列化的
|
||
if (!is_array($result)) {
|
||
\think\facade\Log::error('submitGancaoRecipel result is not array', ['result' => $result]);
|
||
return $this->fail('返回数据格式错误');
|
||
}
|
||
|
||
return $this->success('甘草药方上传成功', $result);
|
||
} catch (\Throwable $e) {
|
||
\think\facade\Log::error('submitGancaoRecipel exception', [
|
||
'message' => $e->getMessage(),
|
||
'file' => $e->getFile(),
|
||
'line' => $e->getLine(),
|
||
'trace' => $e->getTraceAsString()
|
||
]);
|
||
return $this->fail('系统错误:' . $e->getMessage());
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 甘草药管家:预下单测试(仅 CTM_PREVIEW,不提交订单)
|
||
* 用于在编辑订单时测试价格和配置
|
||
*/
|
||
public function previewGancaoRecipel()
|
||
{
|
||
try {
|
||
$params = (new PrescriptionOrderValidate())->post()->goCheck('previewGancaoRecipel');
|
||
$result = PrescriptionOrderLogic::previewGancaoRecipel((int) $params['id'], $this->adminId, $this->adminInfo, $params);
|
||
|
||
if ($result === false) {
|
||
$error = PrescriptionOrderLogic::getError();
|
||
\think\facade\Log::error('previewGancaoRecipel failed', ['error' => $error, 'params' => $params]);
|
||
return $this->fail($error);
|
||
}
|
||
|
||
return $this->success('预下单成功', $result);
|
||
} catch (\Throwable $e) {
|
||
\think\facade\Log::error('previewGancaoRecipel exception', [
|
||
'message' => $e->getMessage(),
|
||
'file' => $e->getFile(),
|
||
'line' => $e->getLine()
|
||
]);
|
||
return $this->fail('系统错误:' . $e->getMessage());
|
||
}
|
||
}
|
||
}
|