353 lines
12 KiB
PHP
353 lines
12 KiB
PHP
<?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;
|
||
}
|
||
}
|