hospital-applets-api/app/Amqp/Consumer/AssignDoctorConsumer.php

271 lines
10 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
declare(strict_types=1);
namespace App\Amqp\Consumer;
use App\Model\OrderInquiry;
use App\Model\UserDoctor;
use App\Services\ImService;
use App\Services\InquiryService;
use App\Services\UserDoctorService;
use App\Utils\Log;
use Extend\TencentIm\Message;
use Extend\Wechat\WechatPay;
use GuzzleHttp\Exception\GuzzleException;
use Hyperf\Amqp\Result;
use Hyperf\Amqp\Annotation\Consumer;
use Hyperf\Amqp\Message\ConsumerMessage;
use Hyperf\DbConnection\Db;
use Hyperf\Redis\Redis;
use Hyperf\Snowflake\IdGeneratorInterface;
use PhpAmqpLib\Message\AMQPMessage;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
/**
* 分配医生
* 快速问诊、问诊购药等订单支付完成后,进行分配医生
*/
#[Consumer(exchange: 'amqp.direct', routingKey: 'AssignDoctor', queue: 'assign.doctor.queue', nums: 1)]
class AssignDoctorConsumer extends ConsumerMessage
{
/**
* @param $data
* [
* "order_inquiry_id":"问诊订单id"
* ]
* @param AMQPMessage $message
* @return string
* @throws ContainerExceptionInterface
* @throws GuzzleException
* @throws NotFoundExceptionInterface
*/
public function consumeMessage($data, AMQPMessage $message): string
{
Log::getInstance()->error("开始执行 分配医生 队列:" . json_encode($data, JSON_UNESCAPED_UNICODE));
Db::beginTransaction();
try {
// 获取订单数据
$params = array();
$params['order_inquiry_id'] = $data['order_inquiry_id'];
$order_inquiry = OrderInquiry::getOne($params);
if (empty($order_inquiry)) {
Db::rollBack();
Log::getInstance()->error("分配医生队列执行失败:未查询到对应订单数据");
return Result::DROP;// 销毁
}
// 检测订单分配状态
if (!empty($order_inquiry['doctor_id'])) {
Db::rollBack();
Log::getInstance()->error("分配医生队列执行失败:已分配医生");
return Result::DROP;// 销毁
}
// 检测订单类型
if ($order_inquiry['inquiry_type'] != 2 && $order_inquiry['inquiry_type'] != 4) {
Db::rollBack();
Log::getInstance()->error("分配医生队列执行失败:订单非快速问诊、问诊购药类型");
return Result::DROP;// 销毁
}
// 检测订单退款状态
if (in_array($order_inquiry['inquiry_refund_status'], [1, 2, 3])) {
Db::rollBack();
// 问诊订单退款状态0:无退款 1:申请退款 2:退款中 3:退款成功 4:拒绝退款 5:退款关闭)
Log::getInstance()->error("分配医生队列执行失败:订单存在退款");
return Result::DROP;// 销毁
}
// 检测订单状态
if ($order_inquiry['inquiry_status'] != 2) {
Db::rollBack();
// 问诊订单状态1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消)
Log::getInstance()->error("分配医生队列执行失败:订单状态错误:当前为" . $order_inquiry['inquiry_status'] . " 无法进行分配");
return Result::DROP;// 销毁
}
// 检测订单支付状态
if ($order_inquiry['inquiry_pay_status'] != 2) {
Db::rollBack();
// 支付状态1:未支付 2:已支付 3:支付中 4:支付失败 5:支付超时 6:支付关闭 7:已撤销 8:转入退款)
Log::getInstance()->error("分配医生队列执行失败:订单支付状态错误:当前为" . $order_inquiry['inquiry_pay_status'] . " 无法进行分配");
return Result::DROP;// 销毁
}
// 检测分配时间
$pay_time = strtotime($order_inquiry['pay_time']);
$diff_time = time() - $pay_time;
if ($diff_time < 0) {
Db::rollBack();
Log::getInstance()->error("分配医生队列执行失败:订单支付状态错误:时间计算错误");
return Result::DROP;// 销毁
}
// 超出5分钟执行退款
if ($diff_time > 300) {
Log::getInstance()->error("分配医生队列执行失败:超出5分钟执行退款");
// 检测问诊订单执行退款次数
$res = $this->checkInquiryRefundCount($order_inquiry['order_inquiry_id']);
if (!$res){
Db::rollBack();
Log::getInstance()->error("分配医生队列执行失败原因:超出最大退款次数");
return Result::ACK;
}
$InquiryService = new InquiryService();
$InquiryService->inquiryRefund($order_inquiry['order_inquiry_id'], "暂无医生接诊");
return Result::ACK;
}
// 分配医生
$UserDoctorService = new UserDoctorService();
$doctor_id = $UserDoctorService->getInquiryAssignDoctor($order_inquiry['inquiry_type'],$order_inquiry['patient_id']);
if (!empty($doctor_id)){
// 无合适医生
Db::rollBack();
Log::getInstance()->error("分配医生队列执行失败原因:重回队列,目前没有合适医生");
$redis_value = $this->checkAssignCount($order_inquiry['order_inquiry_id']);
// 执行睡眠,防止重复执行队列
// 执行规则第一次30秒第二次30秒。以30的倍数增加
sleep($redis_value * 30);
return Result::REQUEUE; // 重回队列
}
// 更改数据库
$data = array();
$data['doctor_id'] = $doctor_id;
$data['inquiry_status'] = 3; // 待接诊
$params = array();
$params['order_inquiry_id'] = $order_inquiry['order_inquiry_id'];
OrderInquiry::edit($params, $data);
Db::commit();
Log::getInstance()->error("分配医生 队列执行成功");
} catch (\Exception $e) {
Db::rollBack();
Log::getInstance()->error("分配医生队列执行失败原因:" . $e->getMessage());
return Result::REQUEUE; // 重回队列
}
try {
// 分配医生成功,发送消息
$ImService = new ImService();
// 获取订单医生数据
$params = array();
$params['doctor_id'] = $doctor_id;
$user_doctor = UserDoctor::getOne($params);
if (empty($user_doctor)) {
Log::getInstance()->info("医生数据错误");
return Result::ACK;
}
// 发送消息
// 自定义消息
$cloud_custom_data = array();
$cloud_custom_data['order_inquiry_id'] = $order_inquiry['order_inquiry_id'];
$cloud_custom_data['is_system'] = 1;
$cloud_custom_data['inquiry_type'] = $order_inquiry['inquiry_type'];
// 消息内容
$message_content_data = array();
$message_content_data['message_type'] = 1;
$message_content_data['content'] = "--等待医生接诊--";
$message_content_data['desc'] = "温馨提示:您可继续补充问诊内容,便于更快确认病情,医生均在临床一线工作,还请耐心等待,医生接诊会第一时间短信通知您。";
$message_content = [
'Data' => json_encode($message_content_data,JSON_UNESCAPED_UNICODE),
];
$ImService->sendMessage($user_doctor['user_id'], $order_inquiry['user_id'], $message_content, "TIMCustomElem", $cloud_custom_data);
Log::getInstance()->info("分配医生成功,发送系统问诊消息成功");
} catch (\Exception $e) {
// 验证失败
Log::getInstance()->error("分配医生成功,发送系统问诊消息失败:" . $e->getMessage());
return Result::ACK;
}
// 加入消息通知队列
return Result::ACK;
}
/**
* 检测问诊订单执行退款次数
* @param string $order_inquiry_id
* @return bool
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
private function checkInquiryRefundCount(string $order_inquiry_id): bool
{
Log::getInstance()->info("检测问诊订单执行退款次数");
try {
$redis = $this->container->get(Redis::class);
$redis_key = "inquiryRefund" . $order_inquiry_id;
$redis_value = $redis->get($redis_key);
if(empty($redis_value)){
$redis->set($redis_key, 1,60 * 60 * 24 * 5);
return true;
}
// 判断退款次数
if ($redis_value > 3) {
Log::getInstance()->error("问诊订单执行退款次数过多");
// 加入短信队列,通知管理员
return false;
}
$redis->incr($redis_key);
} catch (\Exception $e) {
Log::getInstance()->error("检测问诊订单执行退款次数失败:抛出异常" . $e->getMessage());
}
Log::getInstance()->info("检测问诊订单执行退款次数成功");
return true;
}
/**
* 检测问诊订单分配次数
* @param string $order_inquiry_id
* @return int
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
private function checkAssignCount(string $order_inquiry_id): int
{
Log::getInstance()->info("检测问诊订单分配次数");
$redis_value = 1;
try {
$redis = $this->container->get(Redis::class);
$redis_key = "AssignDoctor" . $order_inquiry_id;
$redis_value = $redis->get($redis_key);
if(empty($redis_value)){
$redis->set($redis_key, 1,60 * 60 * 24 * 5);
}else{
$redis_value = $redis->incr($redis_key);
}
} catch (\Exception $e) {
Log::getInstance()->error("检测问诊订单分配次数失败:抛出异常" . $e->getMessage());
}
Log::getInstance()->info("检测问诊订单分配次数成功");
return $redis_value;
}
}