550 lines
19 KiB
PHP
550 lines
19 KiB
PHP
<?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\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") ?? [];
|
||
|
||
$date = $this->request->input('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 = [];
|
||
|
||
$fields = [
|
||
'total_amount',
|
||
'month',
|
||
'day',
|
||
];
|
||
|
||
$params = array();
|
||
$params['doctor_id'] = $user_info['client_user_id'];
|
||
$params['year'] = date('Y', strtotime($date));
|
||
$params['month'] = date('m', strtotime($date));
|
||
$doctor_account_days = DoctorAccountDay::getList($params, $fields);
|
||
if (!empty($doctor_account_days)) {
|
||
foreach ($doctor_account_days as $doctor_account_day) {
|
||
$data = array();
|
||
$data['total_amount'] = floor($doctor_account_day['total_amount'] * 100) / 100;
|
||
$data['month'] = $doctor_account_day['month'];
|
||
$data['day'] = $doctor_account_day['day'];
|
||
$bill[] = $data;
|
||
}
|
||
unset($doctor_account_days);
|
||
}
|
||
|
||
$result = array();
|
||
$result['balance_account'] = floor($balance_account * 100) / 100;; // 账户余额
|
||
$result['amount_total_month'] = floor($amount_total_month * 100) / 100; // 月余额
|
||
$result['withdrawal_amount_month'] = floor($withdrawal_amount_month * 100) / 100; // 月已提现金额
|
||
$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-d 00:00:00', strtotime($date));
|
||
|
||
// 获取当天结束时间
|
||
$end_date = date('Y-m-d 23:59:59', strtotime($date));
|
||
|
||
$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',
|
||
];
|
||
|
||
$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:: getDoctorDateOrderInquiryPage($params, $reception_time, $fields,$page,$per_page);
|
||
if (!empty($order_inquiry['data'])) {
|
||
foreach ($order_inquiry['data'] as &$item) {
|
||
$item['estimate_income'] = floor($item['amount_total'] * 0.75 * 100) / 100;
|
||
}
|
||
}
|
||
|
||
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'];
|
||
|
||
$balance_account = 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)){
|
||
$balance_account = array_sum(array_column($order_inquiry->toArray(),'amount_total'));
|
||
}
|
||
|
||
$order_inquiry_id_array = $in_params;
|
||
}else{
|
||
$InquiryService = new InquiryService();
|
||
$order_inquiry = $InquiryService->getDoctorCanWithdrawalInquiryOrder($user_info['client_user_id']);
|
||
if (!empty($order_inquiry)){
|
||
$balance_account = array_sum(array_column($order_inquiry,'amount_total'));
|
||
$order_inquiry_id_array = array_column($order_inquiry,'order_inquiry_id');
|
||
}
|
||
}
|
||
|
||
if ($balance_account > 0){
|
||
$balance_account = floor($balance_account * 0.75 * 100) / 100;
|
||
}
|
||
|
||
// 计算医生个人所得税
|
||
$income_tax = $this->computeIndividualIncomeTax($balance_account);
|
||
|
||
$withdrawal_amount = floor(($balance_account - $income_tax) * 100) / 100;
|
||
|
||
$income_tax = floor($income_tax * 100) / 100;
|
||
|
||
$result = array();
|
||
$result['bank'] = $bank;//银行数据
|
||
$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("提现金额小于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 += $order_inquiry['amount_total'];
|
||
}
|
||
|
||
// 医生分成金额
|
||
if ($amount_total > 0){
|
||
$amount_total = floor($amount_total * 0.75 * 100) / 100;
|
||
}
|
||
// 计算医生个人所得税
|
||
$income_tax = $this->computeIndividualIncomeTax($amount_total);
|
||
|
||
// 可提现金额
|
||
$withdrawal_amount = floor(($amount_total - $income_tax) * 100) / 100;
|
||
|
||
$income_tax = floor($income_tax * 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['bank_id'] = $doctor_bank_card['bank_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);;
|
||
$data['applied_withdrawal_amount'] = $withdrawal_amount + $income_tax; // 提现金额
|
||
$data['actual_withdrawal_amount'] = $withdrawal_amount; // 实际提现金额
|
||
$data['income_tax'] = $income_tax; // 提现所得税金额
|
||
$data['examine_status'] = 1; // 审核状态(1:审核中 2:审核通过 3:审核未通过)
|
||
$doctor_withdrawal = DoctorWithdrawal::addDoctorWithdrawal($data);
|
||
if (empty($doctor_withdrawal)){
|
||
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',$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|int $income
|
||
* @return float|int
|
||
*/
|
||
protected function computeIndividualIncomeTax(string|int $income): float|int
|
||
{
|
||
if ($income <= 800) {
|
||
return 0;
|
||
}
|
||
|
||
if ($income <= 4000) {
|
||
$income = $income - 800;
|
||
}
|
||
|
||
// 实际纳税金额
|
||
$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;
|
||
}
|
||
} |