hospital-applets-api/app/Services/DoctorAccountService.php

602 lines
22 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
namespace App\Services;
use App\Constants\HttpEnumCode;
use App\Model\BasicBank;
use App\Model\DoctorAccount;
use App\Model\DoctorAccountDay;
use App\Model\DoctorBankCard;
use App\Model\DoctorWithdrawal;
use App\Model\DoctorWithdrawalBank;
use App\Model\DoctorWithdrawalOrder;
use App\Model\OrderInquiry;
use App\Model\UserDoctor;
use App\Model\UserDoctorInfo;
use Hyperf\DbConnection\Db;
/**
* 医生账户
*/
class DoctorAccountService extends BaseService
{
/**
* 获取我的账户数据
* @return array
*/
public function getDoctorAccount(): array
{
$user_info = $this->request->getAttribute("userInfo") ?? [];
$year = $this->request->input('date');
$date = date('Y-m-d',time());
// 今日接诊收入
$inquiryService = new InquiryService();
$doctor_today_inquiry_total = $inquiryService->getDoctorDayAmountTotal($user_info['client_user_id'],$date);
// 今日已完成收入
$doctor_day_completed_amount_total = $inquiryService->getDoctorDayCompletedAmountTotal($user_info['client_user_id'],$date);
// 获取医生账户余额
$balance_account = $this->getDoctorBalanceAccount($user_info['client_user_id']);
// // 获取医生月度余额
// $amount_total_month = $this->getDoctorMonthAmountTotal($user_info['client_user_id'], $date);
//
// // 获取医生月度已提现金额-审核通过时间为准
// $params = array();
// $params['doctor_id'] = $user_info['client_user_id'];
//
// $start_time = date('Y-m-01',strtotime($date));
// $end_time = date('Y-m-t 24:00:00',strtotime($date));
// $created_at = [$start_time,$end_time];
// $doctor_withdrawal = DoctorWithdrawal::getOneLatestTime($params,$created_at,['*']);
// if (empty($doctor_withdrawal)) {
// $withdrawal_amount_month = 0;
// } else {
// $withdrawal_amount_month = $doctor_withdrawal['actual_withdrawal_amount'];
// }
// 获取医生每月账单数据
$bill = [];
$params = array();
$params['doctor_id'] = $user_info['client_user_id'];
$params['year'] = $year;
$doctor_account_days = DoctorAccountDay::getDoctorMonth($params);
if (!empty($doctor_account_days)) {
foreach ($doctor_account_days as $doctor_account_day) {
$data = array();
$data['total_amount'] = bcmul($doctor_account_day['total_amount'],1,2);
$data['month'] = $doctor_account_day['month'];
$bill[] = $data;
}
unset($doctor_account_days);
}
$result = array();
$result['doctor_today_inquiry_total'] = bcmul($doctor_today_inquiry_total,0.75,2); // 今日接诊收入
$result['doctor_day_completed_amount_total'] = bcmul($doctor_day_completed_amount_total ,0.75,2); // 今日已完成收入
$result['balance_account'] = bcmul($balance_account ,1,2); // 账户余额
$result['bill'] = $bill; // 账单
return success($result);
}
/**
* 获取我的账户月账单明细数据
* @return array
*/
public function getDoctorAccountInfo(): array
{
$user_info = $this->request->getAttribute("userInfo") ?? [];
$date = $this->request->input('date');
$page = $this->request->input('page', 1);
$per_page = $this->request->input('per_page', 10);
// 获取当月开始时间
$start_date = date('Y-m-01 00:00:00', strtotime($date));
// 获取当月结束时间
// 获取给定月份的下一个月的第一天,然后减去一天得到当月的最后一天
$end_date = date("Y-m-d 23:59:59", strtotime("+1 month", strtotime($start_date)) - 1);
$reception_time = [$start_date, $end_date];
// 获取医生当日接诊订单金额
$fields = [
'order_inquiry_id',
'inquiry_type',
'inquiry_mode',
'inquiry_status',
'inquiry_refund_status',
'inquiry_no',
'amount_total',
'payment_amount_total',
'reception_time',
'finish_time',
'patient_name',
'patient_sex',
'patient_age',
'cancel_reason',
'cancel_remarks',
'created_at',
];
$params = array();
$params['doctor_id'] = $user_info['client_user_id'];
$inquiry_status_params = [4,5,6,7]; // 问诊订单状态1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消)
$order_inquiry = OrderInquiry:: getDoctorCreatedDateOrderInquiryPage($params, $reception_time, $inquiry_status_params,$fields,$page,$per_page);
if (!empty($order_inquiry['data'])) {
foreach ($order_inquiry['data'] as &$item) {
$item['estimate_income'] = bcmul($item['amount_total'],0.75,2);
// 入账状态
if ($item['inquiry_status'] == 4 || $item['inquiry_status'] == 5){
$item['entry_status'] = 1;// 入账中
}elseif ($item['inquiry_status'] == 6){
$item['entry_status'] = 2;// 入账成功
}elseif ($item['inquiry_status'] == 7){
$item['entry_status'] = 3;// 入账失败
if (!empty($item['cancel_reason'])){
$item['cancel_reason'] = inquiryCancelReasonToPushString($item['cancel_reason']);
}
}else{
$item['entry_status'] = 0;// 未知
}
}
}
return success($order_inquiry);
}
/**
* 获取提现数据
* @return array
*/
public function getDoctorWithdrawalInfo(): array
{
$user_info = $this->request->getAttribute("userInfo") ?? [];
$order_inquiry_ids = $this->request->input('order_inquiry_ids');
// 获取医生信息
$params = array();
$params['doctor_id'] = $user_info['client_user_id'];
$fields = [
'doctor_id',
'user_name',
'iden_auth_status',
'idcard_status',
'multi_point_status',
'avatar',
'is_bind_bank',
];
$user_doctor = UserDoctor::getOne($params, $fields);
if (empty($user_doctor)) {
return fail(HttpEnumCode::HTTP_ERROR, "非法医生");
}
$params = array();
$params['doctor_id'] = $user_info['client_user_id'];
$user_doctor_info = UserDoctorInfo::getOne($params);
if (empty($user_doctor_info)) {
return fail(HttpEnumCode::HTTP_ERROR, "非法医生");
}
// 检测医生身份认证
$UserDoctorService = new UserDoctorService();
$res = $UserDoctorService->checkDoctorAuth($user_doctor);
if ($res !== true) {
return fail(HttpEnumCode::HTTP_ERROR, $res);
}
if ($user_doctor['is_bind_bank'] != 1) {
return fail(HttpEnumCode::HTTP_ERROR, "未绑定结算银行卡");
}
// 获取医生结算银行卡
$params = array();
$params['doctor_id'] = $user_info['client_user_id'];
$doctor_bank_card = DoctorBankCard::getWithBankOne($params);
if (empty($doctor_bank_card)) {
return success();
}
$bank = array();
$bank['bank_card_id'] = $doctor_bank_card['bank_card_id'];
$bank['bank_icon_path'] = addAliyunOssWebsite($doctor_bank_card['BasicBank']['bank_icon_path']);
$bank['bank_name'] = $doctor_bank_card['BasicBank']['bank_name'];
$bank['bank_card_code_mask'] = $doctor_bank_card['bank_card_code_mask'];
$bank['bank_card_name'] = $user_doctor_info['card_name'];
$bank['bank_card_name_mask'] = $user_doctor_info['card_name_mask'];
$amount_total = 0;
$order_inquiry_id_array = [];
// 获取医生账户余额
if (!empty($order_inquiry_ids)){
$params = array();
$params['doctor_id'] = $user_info['client_user_id'];
$params['inquiry_status'] = 6; // inquiry_status问诊订单状态1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消)
$params['inquiry_refund_status'] = 0; // inquiry_refund_status问诊订单退款状态0:无退款 1:申请退款 2:退款中 3:退款成功 4:拒绝退款 5:退款关闭)
$in_params = explode(',',$order_inquiry_ids);
$order_inquiry = OrderInquiry::getInList($params,$in_params);
if (!empty($order_inquiry)){
foreach ($order_inquiry as $value){
$amount_total = bcadd($amount_total,$value["amount_total"],2);
}
}
$order_inquiry_id_array = $in_params;
}else{
$InquiryService = new InquiryService();
$order_inquiry = $InquiryService->getDoctorCanWithdrawalInquiryOrder($user_info['client_user_id']);
if (!empty($order_inquiry)){
foreach ($order_inquiry as $value){
$amount_total = bcadd($amount_total,$value["amount_total"],2);
}
$order_inquiry_id_array = array_column($order_inquiry,'order_inquiry_id');
}
}
$amount_total = bcmul($amount_total,0.75,2);
// 计算医生个人所得税
$income_tax = $this->computeIndividualIncomeTax($amount_total);
$withdrawal_amount = bcsub($amount_total,$income_tax,2);
$income_tax = bcmul($income_tax,1,2);
$result = array();
$result['bank'] = $bank;//银行数据
$result['amount_total'] = $amount_total; // 账户余额
$result['withdrawal_amount'] = $withdrawal_amount; // 提现金额
$result['income_tax'] = $income_tax; // 个人所得税
$result['order_inquiry_ids'] = $order_inquiry_id_array; // 订单合集
return success($result);
}
/**
* 获取可提现问诊订单列表
* @return array
*/
public function getDoctorWithdrawalOrderList(): array
{
$user_info = $this->request->getAttribute("userInfo") ?? [];
$page = $this->request->input('page', 1);
$per_page = $this->request->input('per_page', 10);
// 获取医生当日接诊订单金额
$fields = [
'order_inquiry_id',
'inquiry_type',
'inquiry_mode',
'inquiry_status',
'inquiry_refund_status',
'inquiry_no',
'amount_total',
'payment_amount_total',
'reception_time',
'finish_time',
'patient_name',
'patient_sex',
'patient_age',
];
$params = array();
$params['doctor_id'] = $user_info['client_user_id'];
$params['inquiry_status'] = 6; // inquiry_status问诊订单状态1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消)
$params['inquiry_refund_status'] = 0; // inquiry_refund_status问诊订单退款状态0:无退款 1:申请退款 2:退款中 3:退款成功 4:拒绝退款 5:退款关闭)
$order_inquiry = OrderInquiry:: getDoctorOrderInquiryPage($params, $fields,$page,$per_page);
if (!empty($order_inquiry['data'])) {
foreach ($order_inquiry['data'] as &$item) {
$item['expected_amount_total'] = floor($item['amount_total'] * 0.75 * 100) / 100;
}
}
return success($order_inquiry);
}
/**
* 获取医生提现记录列表
* @return array
*/
public function getDoctorWithdrawalRecordList(): array
{
$user_info = $this->request->getAttribute("userInfo") ?? [];
$year = $this->request->input('year');
$page = $this->request->input('page',1);
$per_page = $this->request->input('per_page',10);
// 获取当年开始时间
$start_date = $year.'-1-1 00:00:00';
// 获取当年结束时间
$end_date = $year.'-12-31 23:59:59';
$created_at_params = [$start_date, $end_date];
$params = array();
$params['doctor_id'] = $user_info['client_user_id'];
$doctor_withdrawal = DoctorWithdrawal::getDatePage($params,$created_at_params,['*'],$page,$per_page);
if (empty($doctor_withdrawal['data'])){
return success();
}
return success($doctor_withdrawal);
}
/**
* 发起提现
* @return array
*/
public function addDoctorWithdrawal(): array
{
$user_info = $this->request->getAttribute("userInfo") ?? [];
$order_inquiry_id = $this->request->input('order_inquiry_id');
$withdrawal_amount_total = $this->request->input('withdrawal_amount_total');
$bank_card_id = $this->request->input('bank_card_id');
$order_inquiry_id = explode(',',$order_inquiry_id);
if (empty($order_inquiry_id)){
return fail();
}
$app_env = config('app_env');
if ($app_env != "dev"){
// 正式环境高于300元才可以提现
if ($withdrawal_amount_total < 300){
return fail(HttpEnumCode::HTTP_ERROR,"提现金额小于300元");
}
}
// 每月只能提现一次
$params = array();
$params['doctor_id'] = $user_info['client_user_id'];
$start_time = date('Y-m-01',time());
$end_time = date('Y-m-t 24:00:00',time());
$created_at = [$start_time,$end_time];
$doctor_withdrawal = DoctorWithdrawal::getOneLatestTime($params,$created_at,['*'],);
if (!empty($doctor_withdrawal)){
return fail("每月只允许提现一次");
}
$amount_total = 0;
foreach ($order_inquiry_id as $value){
$params = array();
$params['order_inquiry_id'] = $value;
$params['doctor_id'] = $user_info['client_user_id'];
$order_inquiry = OrderInquiry::getOne($params);
if (empty($order_inquiry)){
return fail(HttpEnumCode::HTTP_ERROR,"存在不可提现订单");
}
// 验证订单状态
if ($order_inquiry['inquiry_status'] != 6){
return fail(HttpEnumCode::HTTP_ERROR,"提现失败");
}
// 验证订单提现状态
if ($order_inquiry['is_withdrawal'] != 0){
return fail(HttpEnumCode::HTTP_ERROR,"存在已提现订单");
}
// 验证订单支付状态
if ($order_inquiry['inquiry_pay_status'] != 2){
return fail(HttpEnumCode::HTTP_ERROR,"存在未支付订单");
}
// 计算订单总金额
$amount_total = bcadd($amount_total,$order_inquiry["amount_total"],2);
}
// 提现金额
$amount_total = $amount_total * 0.75;
// 计算医生个人所得税
$income_tax = $this->computeIndividualIncomeTax($amount_total);
// 实际提现金额
$withdrawal_amount = $amount_total - $income_tax;
if ($withdrawal_amount > 0){
$withdrawal_amount = floor($withdrawal_amount * 100) / 100;
}
if ($withdrawal_amount_total != $withdrawal_amount){
return fail(HttpEnumCode::SERVER_ERROR,"金额不符合");
}
// 检测提现银行卡
$params = array();
$params['bank_card_id'] = $bank_card_id;
$doctor_bank_card = DoctorBankCard::getOne($params);
if (empty($doctor_bank_card)){
return fail(HttpEnumCode::HTTP_ERROR,"银行卡错误");
}
// 获取银行数据
$params = array();
$params['bank_id'] = $doctor_bank_card['bank_id'];
$basic_bank = BasicBank::getOne($params);
if (empty($basic_bank)){
return fail(HttpEnumCode::HTTP_ERROR,"银行卡错误");
}
Db::beginTransaction();
try {
// 新增医生提现表
$data = array();
$data['doctor_id'] = $user_info['client_user_id'];
$data['account_name'] = $basic_bank['bank_name'];
$data['bank_card_code'] = $doctor_bank_card['bank_card_code'];
$data['bank_card_code_four'] = substr($doctor_bank_card['bank_card_code'], -4);
if ($amount_total > 0){
$data['applied_withdrawal_amount'] = floor($amount_total * 100) / 100; // 提现金额
}
$data['actual_withdrawal_amount'] = $withdrawal_amount; // 实际提现金额
if ($income_tax > 0){
$data['income_tax'] = floor($income_tax * 100) / 100; // 提现所得税金额
}
$data['examine_status'] = 1; // 审核状态1:审核中 2:审核通过 3:审核未通过)
$doctor_withdrawal = DoctorWithdrawal::addDoctorWithdrawal($data);
if (empty($doctor_withdrawal)){
Db::rollBack();
return fail(HttpEnumCode::SERVER_ERROR);
}
// 新增医生提现表-关联银行
$data = array();
$data['withdrawal_id'] = $doctor_withdrawal["withdrawal_id"];
$data['bank_id'] = $doctor_bank_card['bank_id'];
$data['bank_card_code'] = $doctor_bank_card['bank_card_code'];
$data['province_id'] = $doctor_bank_card['province_id'];
$data['province'] = $doctor_bank_card['province'];
$data['city_id'] = $doctor_bank_card['city_id'];
$data['city'] = $doctor_bank_card['city'];
$data['county_id'] = $doctor_bank_card['county_id'];
$data['county'] = $doctor_bank_card['county'];
$doctor_withdrawal_bank = DoctorWithdrawalBank::addDoctorWithdrawalBank($data);
if (empty($doctor_withdrawal_bank)){
Db::rollBack();
return fail(HttpEnumCode::SERVER_ERROR);
}
foreach ($order_inquiry_id as $value){
// 新增医生提现-关联订单表
$data = array();
$data['withdrawal_id'] = $doctor_withdrawal['withdrawal_id'];
$data['doctor_id'] = $user_info['client_user_id'];
$data['order_inquiry_id'] = $value;
$doctor_withdrawal_order = DoctorWithdrawalOrder::addDoctorWithdrawalOrder($data);
if (empty($doctor_withdrawal_order)){
Db::rollBack();
return fail(HttpEnumCode::SERVER_ERROR);
}
// 修改问诊订单提现状态
$params = array();
$params['order_inquiry_id'] = $value;
$data = array();
$data['is_withdrawal'] = 2;
$data['withdrawal_time'] = date('Y-m-d H:i:s',time());
OrderInquiry::edit($params,$data);
}
// 账户表锁定
$params = array();
$params['doctor_id'] = $user_info['client_user_id'];
// 账户余额
DoctorAccount::dec($params,'balance_account',$amount_total);
// 提现金额
DoctorAccount::inc($params,'applied_withdrawal_amount',$amount_total);
// 实际提现金额
DoctorAccount::inc($params,'actual_withdrawal_amount',$withdrawal_amount);
// 所得税金额
DoctorAccount::inc($params,'income_tax',$income_tax);
Db::commit();
return success();
} catch (\Exception $e) {
Db::rollBack();
return fail(HttpEnumCode::SERVER_ERROR,$e->getMessage());
}
}
/**
* 获取医生账户余额
* @param string $doctor_id
* @return float
*/
public function getDoctorBalanceAccount(string $doctor_id): float
{
$params = array();
$params['doctor_id'] = $doctor_id;
$doctor_account = DoctorAccount::getOne($params);
if (empty($doctor_account)) {
$balance_account = 0;
} else {
$balance_account = $doctor_account['balance_account'];
}
return $balance_account;
}
/**
* 获取某月医生账户已结束订单金额
* @param string $doctor_id 医生id
* @param string $date 日期 Ymd形式
* @return float|int|mixed|string
*/
public function getDoctorMonthAmountTotal(string $doctor_id, string $date): mixed
{
$params = array();
$params['doctor_id'] = $doctor_id;
$params['year'] = date('Y', strtotime($date));
$params['month'] = date('m', strtotime($date));
$total_amount = DoctorAccountDay::getDoctorSumTotalAmount($params);
if (empty($total_amount)) {
$total_amount = 0;
}
return $total_amount;
}
/**
* 计算个人所得税
* @param string|float $income
* @return float
*/
protected function computeIndividualIncomeTax(string|float $income): float
{
if ($income <= 800) {
return 0;
}
if ($income <= 4000) {
$income = $income - 800;
}
// 实际纳税金额
if ($income > 4000){
$income = $income * 0.8;
}
if ($income <= 20000) {
$tax_rate = 0.2; // 税率
$quick_deduction = 0; // 速算扣除数
} elseif ($income <= 50000) {
$tax_rate = 0.3;// 税率
$quick_deduction = 2000; // 速算扣除数
} else {
$tax_rate = 0.4;
$quick_deduction = 7000; // 速算扣除数
}
$income_tax = $income * $tax_rate - $quick_deduction;
return $income_tax;
}
}