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

353 lines
12 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\Amqp\Producer\AutoCompleteServicePackageDelayDirectProducer;
use App\Model\DoctorAccount;
use App\Model\DoctorAccountDay;
use App\Model\OrderServicePackage;
use App\Model\OrderServicePackageDetail;
use App\Model\OrderServicePackageInquiry;
use App\Model\UserDoctor;
use App\Services\MessagePush;
use App\Services\OrderPrescriptionService;
use App\Services\OrderServicePackageService;
use App\Utils\Log;
use App\Utils\Utils;
use Hyperf\Amqp\Message\ConsumerDelayedMessageTrait;
use Hyperf\Amqp\Message\ProducerDelayedMessageTrait;
use Hyperf\Amqp\Message\Type;
use Hyperf\Amqp\Producer;
use Hyperf\Amqp\Result;
use Hyperf\Amqp\Annotation\Consumer;
use Hyperf\Amqp\Message\ConsumerMessage;
use Hyperf\DbConnection\Db;
use PhpAmqpLib\Message\AMQPMessage;
/**
* 自动完成服务包订单
* 延迟队列
*/
#[Consumer(nums: 1)]
class AutoCompleteServicePackageDelayDirectConsumer extends ConsumerMessage
{
use ProducerDelayedMessageTrait;
use ConsumerDelayedMessageTrait;
protected string $exchange = 'amqp.delay.direct';
protected ?string $queue = 'auto.complete.service.package.delay.queue';
protected string $type = Type::DIRECT; //Type::FANOUT;
protected string|array $routingKey = 'AutoCompleteServicePackage';
public function consumeMessage($data, AMQPMessage $message): string
{
Log::getInstance("queue-AutoCompleteServicePackage")->info(json_encode($data, JSON_UNESCAPED_UNICODE));
try {
// 检测执行次数
$Utils = new Utils();
$redis_key = "CompleteServicePackage" . $data['order_no'];
$res = $Utils->checkHandleNumber($redis_key);
if (!$res) {
Log::getInstance("queue-AutoCompleteServicePackage")->error("超出最大执行次数或检测错误");
return Result::ACK;
}
}catch (\Throwable $e){
Log::getInstance("queue-AutoCompleteServicePackage")->error($e->getMessage());
return Result::REQUEUE;
}
try {
// 检测入参参数
$res = $this->detectInputParameters($data);
if (!$res){
Log::getInstance("queue-AutoCompleteServicePackage")->error("入参错误" );
return Result::ACK;
}
// 获取订单数据
$params = array();
$params['order_service_no'] = $data['order_no'];
$order_service_package = OrderServicePackage::getOne($params);
if (empty($order_service_package)){
Log::getInstance("queue-AutoCompleteServicePackage")->error("订单错误" );
return Result::ACK;
}
// 检测订单状态
$res = $this->detectOrderStatus($order_service_package);
if (!$res){
Log::getInstance("queue-AutoCompleteServicePackage")->error("订单状态错误" );
return Result::ACK;
}
// 检测订单结束时间
$res = $this->detectOrderFinishTime($order_service_package);
if (!$res){
// 未到结束时间,重新加入队列
$res = $this->addQueue($order_service_package);
if (!$res){
// 重新添加队列失败
return Result::REQUEUE;
}
return Result::DROP;
}
// 获取订单详情数据
$params = array();
$params['order_service_no'] = $data['order_no'];
$order_service_package_detail = OrderServicePackageDetail::getOne($params);
if (empty($order_service_package_detail)){
Log::getInstance("queue-AutoCompleteServicePackage")->error("订单详情错误" );
return Result::ACK;
}
}catch (\Throwable $e){
Log::getInstance("queue-AutoCompleteServicePackage")->error($e->getMessage());
return Result::REQUEUE;
}
// 处理业务
Db::beginTransaction();
try {
// 处理服务包订单为已完成
$data = array();
$data['order_service_status'] = 4;// 订单状态1:待支付 2:未开始 3:服务中 4:服务完成 5:服务取消)
$params = array();
$params['order_service_id'] = $order_service_package['order_service_id'];
OrderServicePackage::edit($params,$data);
// 处理统计问题
// 获取服务包订单中医生可分成的问诊金额
$OrderServicePackageService = new OrderServicePackageService();
$amount_total = $OrderServicePackageService->getServicePackageDoctorInquiryAmountTotal($order_service_package['order_service_no'],$order_service_package,$order_service_package_detail);
if ($amount_total > 0){
// 处理医生账户总表
$res = $this->handleDoctorAccount($amount_total,$order_service_package['doctor_id']);
if (!$res) {
Db::rollBack();
return Result::REQUEUE;
}
// 处理医生账户表-日
$res = $this->handleDoctorAccountDay($amount_total,$order_service_package['doctor_id'],$order_service_package['start_time']);
if (!$res) {
Db::rollBack();
return Result::REQUEUE;
}
}
Db::commit();
}catch (\Throwable $e){
Db::rollBack();
Log::getInstance("queue-AutoCompleteServicePackage")->error($e->getMessage());
return Result::REQUEUE;
}
// 发送消息
try {
// 获取订单医生数据
$params = array();
$params['doctor_id'] = $order_service_package['doctor_id'];
$user_doctor = UserDoctor::getOne($params);
if (empty($user_doctor)) {
Log::getInstance("queue-AutoCompleteServicePackage")->error("医生数据错误");
return Result::ACK;
}
// 医生-通知医生患者的服务包服务结束
$MessagePush = new MessagePush($user_doctor['user_id'], $order_service_package['order_service_no']);
$MessagePush->doctorServicePackageFinish();
// 患者-通知患者服务包服务已结束
$MessagePush = new MessagePush($order_service_package['user_id'], $order_service_package['order_service_no']);
$MessagePush->patientServicePackageFinish();
}catch (\Throwable $e){
Log::getInstance("queue-AutoCompleteServicePackage")->error($e->getMessage());
return Result::ACK;
}
return Result::ACK;
}
/**
* 检测入参参数
* @param array $data
* @return bool
*/
public function detectInputParameters(array $data): bool
{
if (empty($data['order_no'])){
return false;
}
return true;
}
/**
* 检测订单状态
* @param array|object $order_service_package
* @return bool
*/
public function detectOrderStatus(array|object $order_service_package): bool
{
if ($order_service_package['order_service_status'] == 1){
Log::getInstance("queue-AutoCompleteServicePackage")->error("订单未支付" );
return false;
}
if ($order_service_package['order_service_status'] == 2){
Log::getInstance("queue-AutoCompleteServicePackage")->error("订单未开始" );
return false;
}
if ($order_service_package['order_service_status'] == 4){
Log::getInstance("queue-AutoCompleteServicePackage")->error("订单已完成" );
return false;
}
// 订单支付状态
if ($order_service_package['pay_status'] != 2){
Log::getInstance("queue-AutoCompleteServicePackage")->error("订单未支付" );
return false;
}
return true;
}
/**
* 检测订单结束时间
* @param array|object $order_service_package
* @return bool
*/
public function detectOrderFinishTime(array|object $order_service_package): bool
{
$finish_time = strtotime($order_service_package['finish_time']);
$diff_time = time() - $finish_time;
if ($diff_time < 0 && ($diff_time > -7200)){
// 负数,表示还未到完成时间。重新加入队列
return false;
}
// 正数,已到或已超完成时间。可以取消。
return true;
}
/**
* 重新加入队列
* @param array|object $order_service_package
* @return bool
*/
public function addQueue(array|object $order_service_package): bool
{
try {
$finish_time = strtotime($order_service_package['finish_time']);
// 结束时间大于当前时间
if ($finish_time > time()){
$time = $finish_time - time();
$queue_data = array();
$queue_data['order_no'] = $order_service_package['order_service_no'];
$message = new AutoCompleteServicePackageDelayDirectProducer($queue_data);
$message->setDelayMs(1000 * $time);
$producer = $this->container->get(Producer::class);
$res = $producer->produce($message);
if (!$res) {
return false;
}
}
}catch (\Throwable $e){
Log::getInstance("queue-AutoCompleteServicePackage")->error($e->getMessage());
return false;
}
return true;
}
/**
* 处理医生账户总表
* 创建/修改医生账户总表中总金额、账户余额数据
* @param string|int $amount_total
* @param string|int $doctor_id
* @return bool
*/
protected function handleDoctorAccount(string|int $amount_total,string|int $doctor_id): bool
{
$params = array();
$params['doctor_id'] = $doctor_id;
$doctor_account = DoctorAccount::getOne($params);
if (empty($doctor_account)) {
// 首次
$data = array();
$data['doctor_id'] = $doctor_id;
$data['total_amount'] = $amount_total;
$data['balance_account'] = $amount_total;
$data['applied_withdrawal_amount'] = 0;
$data['actual_withdrawal_amount'] = 0;
$data['income_tax'] = 0;
$doctor_account = DoctorAccount::addDoctorAccount($data);
if (empty($doctor_account)) {
return false;
}
} else {
// 非首次
// 总金额(已结束订单的总金额)
$params = array();
$params['account_id'] = $doctor_account['account_id'];
DoctorAccount::inc($params, 'total_amount', (float)$amount_total);
// 账户余额
DoctorAccount::inc($params, 'balance_account', (float)$amount_total);
}
return true;
}
/**
* 处理医生账户表-日
* @param string|int $amount_total
* @param string|int $doctor_id
* @param string $start_time
* @return bool
*/
protected function handleDoctorAccountDay(string|int $amount_total,string|int $doctor_id,string $start_time): bool
{
$params = array();
$params['doctor_id'] = $doctor_id;
$params['date'] = date('Y-m-d', strtotime($start_time));
$doctor_account_day = DoctorAccountDay::getOne($params);
if (empty($doctor_account_day)) {
// 当日首次
$data = array();
$data['doctor_id'] = $doctor_id;
$data['year'] = date('Y', strtotime($start_time));
$data['month'] = date('m', strtotime($start_time));
$data['day'] = date('d', strtotime($start_time));
$data['date'] = date('Y-m-d', strtotime($start_time));
$data['total_amount'] = $amount_total;
$doctor_account_day = DoctorAccountDay::addDoctorAccountDay($data);
if (empty($doctor_account_day)) {
return false;
}
} else {
// 非当日首次
$params = array();
$params['account_detail_id'] = $doctor_account_day['account_detail_id'];
DoctorAccountDay::inc($params, 'total_amount', (float)$amount_total);
}
return true;
}
}