You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
309 lines
11 KiB
309 lines
11 KiB
<?php
|
|
declare(strict_types = 1);
|
|
|
|
namespace App\Http\Logics\Patient;
|
|
|
|
use App\Dictionary\Patient\CardType;
|
|
use App\Dictionary\Patient\Sex;
|
|
use App\Dictionary\WeChat\MiniProgram\OpenApi;
|
|
use App\Exceptions\GeneralException;
|
|
use App\Models\Patient;
|
|
use App\Services\HisHttp\Client;
|
|
use App\Utils\Traits\Logger;
|
|
use App\Utils\Traits\MiniProgramAuth;
|
|
use App\Utils\Traits\SendSubscribeMessage;
|
|
use App\Utils\Traits\UniversalEncryption;
|
|
use Exception;
|
|
use Illuminate\Auth\AuthenticationException;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
use Symfony\Contracts\HttpClient\Exception\ExceptionInterface;
|
|
|
|
class PatientLogic
|
|
{
|
|
use Logger;
|
|
use MiniProgramAuth;
|
|
use UniversalEncryption;
|
|
use SendSubscribeMessage;
|
|
|
|
private Client $his_client;
|
|
|
|
private Patient $patient_model;
|
|
|
|
/**
|
|
* PatientLogic Construct
|
|
* @throws AuthenticationException
|
|
*/
|
|
public function __construct()
|
|
{
|
|
$this->authInitialize();
|
|
$this->patient_model = new Patient();
|
|
$this->his_client = app('HisHttpService');
|
|
}
|
|
|
|
/**
|
|
* 获取绑定患者列表
|
|
*/
|
|
public function getAllPatientLists()
|
|
{
|
|
return $this->patient_model->getBindPatientLists($this->open_id);
|
|
}
|
|
|
|
/**
|
|
* 卡详情
|
|
* @param string $patient_number
|
|
* @return Patient
|
|
* @throws GeneralException
|
|
*/
|
|
public function getPatientDetails(string $patient_number): Patient
|
|
{
|
|
$info = $this->patient_model->getBindPatientInfoByPatientNumber($this->open_id, $patient_number);
|
|
if(empty($info)) {
|
|
throw new GeneralException('找不到该就诊卡!');
|
|
}
|
|
|
|
// 获取患者信息
|
|
$response = $this->his_client->getPatientInfo($info['patient_number'], CardType::OUTPATIENT_NO, $info['name']);
|
|
if (!isset($response['success']) || !$response['success']) {
|
|
throw new GeneralException($response['msg'] ?? '找不到该就诊卡!', Response::HTTP_SERVICE_UNAVAILABLE);
|
|
}
|
|
|
|
$info->birthday = $response['response']['birthday'] ?? '';
|
|
|
|
return $info;
|
|
}
|
|
|
|
/**
|
|
* 建档
|
|
* @param array $data
|
|
* @return string
|
|
* @throws GeneralException
|
|
*/
|
|
public function createPatient(array $data): string
|
|
{
|
|
// 简单判断一下证件类型
|
|
$card_type = getIDCardType($data['card_no']);
|
|
switch ($card_type) {
|
|
// 身份证
|
|
case 1:
|
|
$sex = getGenderByIdCard($data['card_no']) === 1 ? Sex::MALE : Sex::WOMEN;
|
|
$birthday = getBirthdayByIdCard($data['card_no']);
|
|
break;
|
|
// 2017 / 2023 外国人永居证
|
|
case 3:
|
|
case 4:
|
|
if ($card_type == 3) {
|
|
$sex = Sex::from((int)$data['sex']);
|
|
$birthday = getBirthdayBy2017ForeignersIDCard($data['card_no']);
|
|
} else {
|
|
$sex = getGenderByIdCard($data['card_no']) === 1 ? Sex::MALE : Sex::WOMEN;
|
|
$birthday = getBirthdayByIdCard($data['card_no']);
|
|
}
|
|
break;
|
|
default:
|
|
$sex = Sex::from((int)$data['sex']);
|
|
$birthday = &$data['birthday'];
|
|
break;
|
|
}
|
|
|
|
//过滤名字特殊字符
|
|
$data['name'] = replaceSpecialChar($data['name']);
|
|
$card_type = CardType::from((int)$data['card_type']);
|
|
|
|
// 查询绑定超过X个
|
|
$bind_count = $this->patient_model->getBindPatientCount($this->open_id);
|
|
if ($bind_count >= config('custom.max_bind_patient_count')) {
|
|
throw new GeneralException('该微信达到绑定卡上限!');
|
|
}
|
|
|
|
// 查询患者信息
|
|
$response = $this->his_client->getPatientInfo($data['card_no'], $card_type, $data['name']);
|
|
$this->info('查询患者信息:', $response);
|
|
|
|
if (!isset($response['success']) || !$response['success']) {
|
|
$patient_id = &$response['response']['patientNumber'];
|
|
|
|
// 查询是否已绑定
|
|
$result = $this->patient_model->getPatientInfoByPatientId($patient_id);
|
|
if ($result && $result['open_id'] == $this->open_id) {
|
|
throw new GeneralException('您已绑定该就诊卡号!');
|
|
}
|
|
|
|
if ($result && $result['open_id'] != $this->open_id) {
|
|
throw new GeneralException('该卡号已被其他微信用户绑定!');
|
|
}
|
|
} else {
|
|
// 查询失败,走建档
|
|
$response = $this->his_client->registerCard(
|
|
$data['card_no'],
|
|
$card_type,
|
|
$data['name'],
|
|
$sex,
|
|
$birthday,
|
|
$data['card_no'],
|
|
$data['phone'],
|
|
$data['address']
|
|
);
|
|
$this->info('建档患者:'. $data['name']. '建档结果', $response);
|
|
|
|
if (!isset($response['success']) || !$response['success']) {
|
|
throw new GeneralException('建档失败,失败原因:'. $response['msg'] ?? '未知错误', Response::HTTP_SERVICE_UNAVAILABLE);
|
|
}
|
|
}
|
|
|
|
// 再查一遍接口 获取患者信息
|
|
$response = $this->his_client->getPatientInfo($data['card_no'], $card_type, $data['name']);
|
|
if (!isset($response['success']) || !$response['success']) {
|
|
throw new GeneralException('建档失败,失败原因:'. $response['msg'] ?? '未知错误', Response::HTTP_SERVICE_UNAVAILABLE);
|
|
}
|
|
|
|
$patient_id = $response['response']['patientId'];
|
|
$patient_number = $response['response']['patientNumber'];
|
|
|
|
// 写入数据库
|
|
$result = $this->patient_model->createPatient($this->union_id, $this->open_id, $patient_id, $patient_number, $data['name'], $sex);
|
|
|
|
if (!$result) {
|
|
throw new GeneralException('数据保存失败,请重试!', Response::HTTP_INTERNAL_SERVER_ERROR);
|
|
}
|
|
|
|
$this->sendBindPatientSubscribeMessage($this->open_id, $result->id, $data['name']);
|
|
return $patient_id;
|
|
}
|
|
|
|
/**
|
|
* 绑定患者
|
|
* @param array $data
|
|
* @return string
|
|
* @throws GeneralException
|
|
*/
|
|
public function bindPatient(array $data): string
|
|
{
|
|
//过滤名字特殊字符
|
|
$data['name'] = replaceSpecialChar($data['name']);
|
|
$card_type = CardType::from((int)$data['card_type']);
|
|
|
|
// 查询超过X个
|
|
$bind_count = $this->patient_model->getBindPatientCount($this->open_id);
|
|
if ($bind_count >= config('custom.max_bind_patient_count')) {
|
|
throw new GeneralException('该微信达到绑定卡上限!');
|
|
}
|
|
|
|
// 查询患者信息
|
|
$response = $this->his_client->getPatientInfo($data['card_no'], $card_type, $data['name']);
|
|
$this->info('查询患者信息:', $response);
|
|
|
|
if (!isset($response['success']) || !$response['success']) {
|
|
throw new GeneralException($response['msg'] ?? '未知错误');
|
|
}
|
|
|
|
$patient_info = &$response['response'];
|
|
$patient_id = &$patient_info['patientId'];
|
|
$patient_number = &$patient_info['patientNumber'];
|
|
$sex = Sex::from((int) $patient_info['sex']);
|
|
|
|
if ($patient_info['patientNumber'] != $data['patient_id']) {
|
|
throw new GeneralException('该证件号已建档,但就诊卡号不匹配!');
|
|
}
|
|
|
|
if ($patient_info['name'] != $data['name']) {
|
|
throw new GeneralException('该证件号已建档,但姓名不匹配!');
|
|
}
|
|
|
|
if ($patient_info['cardNo'] != $data['card_no']) {
|
|
throw new GeneralException('该就诊号已建档,但证件号码不匹配!');
|
|
}
|
|
|
|
// 查询是否已绑定
|
|
$result = $this->patient_model->getPatientInfoByPatientId($data['patient_id']);
|
|
if ($result && $result['openid'] == $this->open_id) {
|
|
throw new GeneralException('您已绑定该就诊卡号!');
|
|
}
|
|
|
|
if ($result && $result['openid'] != $this->open_id) {
|
|
throw new GeneralException('该卡号已被其他微信用户绑定!');
|
|
}
|
|
|
|
// 写入数据库
|
|
$result = $this->patient_model->createPatient($this->union_id, $this->open_id, $patient_id, $patient_number, $data['name'], $sex);
|
|
|
|
if (!$result) {
|
|
throw new GeneralException('数据保存失败,请重试!', Response::HTTP_INTERNAL_SERVER_ERROR);
|
|
}
|
|
|
|
$this->sendBindPatientSubscribeMessage($this->open_id, $result->id, $data['name']);
|
|
return $patient_number;
|
|
}
|
|
|
|
/**
|
|
* 设置默认就诊卡
|
|
* @param string $patient_number
|
|
* @return bool
|
|
* @throws GeneralException
|
|
*/
|
|
public function setDefaultPatient(string $patient_number): bool
|
|
{
|
|
$info = $this->patient_model->getBindPatientInfoByPatientNumber($this->open_id, $patient_number);
|
|
if (empty($info)) {
|
|
throw new GeneralException('该就诊卡不存在!');
|
|
}
|
|
|
|
$result = $this->patient_model->setDefaultPatient($this->open_id, $info->patient_id);
|
|
if (!$result) {
|
|
throw new GeneralException('设置失败,请稍后再试!', Response::HTTP_INTERNAL_SERVER_ERROR);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* 解绑
|
|
* @param string $patient_number
|
|
* @return bool
|
|
* @throws GeneralException
|
|
*/
|
|
public function cancelBindPatient(string $patient_number): bool
|
|
{
|
|
$info = $this->patient_model->getBindPatientInfoByPatientNumber($this->open_id, $patient_number);
|
|
if (empty($info)) {
|
|
throw new GeneralException('该就诊卡不存在!');
|
|
}
|
|
|
|
$result = $this->patient_model->deletePatient($this->open_id, $info->patient_id);
|
|
if (!$result) {
|
|
throw new GeneralException('解绑失败,请稍后再试!', Response::HTTP_INTERNAL_SERVER_ERROR);
|
|
}
|
|
|
|
$this->sendUnbindPatientSubscribeMessage($this->open_id, $info->id, $info['name'], ' ', $patient_number);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* 获取患者手机号码
|
|
* @param string $code
|
|
* @return array
|
|
* @throws GeneralException
|
|
*/
|
|
public function getPhoneNumber(string $code): array
|
|
{
|
|
try {
|
|
$mini = getWeChatMiniProgramApp();
|
|
$response = $mini->getClient()->postJson(OpenApi::GET_PHONE_NUMBER->value, [
|
|
'code' => $code
|
|
]);
|
|
|
|
$this->info('获取手机号码接口返回', [$response]);
|
|
|
|
if ($response['errcode'] !== 0 || empty($response['phone_info'])) {
|
|
throw new GeneralException('获取手机号码失败,请稍后再试!');
|
|
}
|
|
|
|
return $response['phone_info'];
|
|
|
|
} catch (ExceptionInterface|Exception $e) {
|
|
//service error
|
|
$message = $e->getMessage() . ' in ' . $e->getFile() . ':' . $e->getLine();
|
|
$this->error('获取手机号码接口报错', [$message]);
|
|
throw new GeneralException('获取手机号码失败,请稍后再试!', Response::HTTP_BAD_REQUEST);
|
|
}
|
|
}
|
|
}
|
|
|