|
|
<?php
|
|
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
|
|
use App\Models\Appointment;
|
|
|
use App\Models\AppointmentHolidays;
|
|
|
use App\Models\AppointmentTemplate;
|
|
|
use App\Models\Hospital;
|
|
|
use App\Models\UserOrder;
|
|
|
use Illuminate\Http\Request;
|
|
|
use Login;
|
|
|
use Yo;
|
|
|
|
|
|
class AppointmentController extends Controller
|
|
|
{
|
|
|
public function month_map($month)
|
|
|
{
|
|
|
$week = date('w', strtotime($month[0]['date']));
|
|
|
if ($week == 0) $week = 7;
|
|
|
$month_list = [
|
|
|
[],
|
|
|
[],
|
|
|
[],
|
|
|
[],
|
|
|
[],
|
|
|
[],
|
|
|
];
|
|
|
for ($i = 0; $i < $week; $i++) {
|
|
|
$month_list[0][] = [
|
|
|
'date' => '',
|
|
|
'day' => 0,
|
|
|
'create' => false,
|
|
|
];
|
|
|
}
|
|
|
foreach ($month as $item) {
|
|
|
$c = date('d', strtotime($item['date'])) + ($week - 2);
|
|
|
$w = date('w', strtotime($item['date']));
|
|
|
if ($w == 0) $w = 7;
|
|
|
$month_list[floor($c / 7)][$w - 1] = $item;
|
|
|
}
|
|
|
foreach ($month_list as $key => $item) {
|
|
|
$c = count($item);
|
|
|
if ($c != 7) {
|
|
|
for ($i = 0; $i < 7 - $c; $i++) {
|
|
|
$month_list[$key][] = [
|
|
|
'date' => '',
|
|
|
'day' => 0,
|
|
|
'create' => false,
|
|
|
];
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
return $month_list;
|
|
|
}
|
|
|
|
|
|
public function last_day($date)
|
|
|
{
|
|
|
$date = strtotime($date);
|
|
|
$count = cal_days_in_month(CAL_GREGORIAN, date('m', $date), date('Y', $date));
|
|
|
return date('Y-m', $date) . '-' . $count;
|
|
|
}
|
|
|
|
|
|
public function first_day($date)
|
|
|
{
|
|
|
$date = strtotime($date);
|
|
|
return date('Y-m-01', $date);
|
|
|
}
|
|
|
|
|
|
public function check_create($appointment_template, $date, $list)
|
|
|
{
|
|
|
$weekday = $appointment_template->weekday;
|
|
|
$holidays = $appointment_template->holidays;
|
|
|
$weeks = json_decode($appointment_template->weeks, true);
|
|
|
$week = date('w', strtotime($date));
|
|
|
$week = $week == 0 ? 7 : $week;
|
|
|
switch ($week) {
|
|
|
case 1:
|
|
|
case 2:
|
|
|
case 3:
|
|
|
case 4:
|
|
|
case 5:
|
|
|
if (isset($list[$date]) && $list[$date]['type'] == 1) {
|
|
|
if ($holidays == 2) return false;
|
|
|
}
|
|
|
return in_array((string)$week, $weeks);
|
|
|
case 6:
|
|
|
case 7:
|
|
|
if (isset($list[$date]) && $list[$date]['type'] == 2) {
|
|
|
if ($weekday == 1) return true;
|
|
|
}
|
|
|
return in_array((string)$week, $weeks);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
public function date_map($start_date, $end_date, $appointment_template, $list)
|
|
|
{
|
|
|
$date_map = [];
|
|
|
$first_day = self::first_day($start_date);
|
|
|
$last_day = self::last_day($end_date);
|
|
|
$first_day_time = strtotime($first_day);
|
|
|
$last_day_time = strtotime($last_day);
|
|
|
for ($i = $first_day_time; $i <= $last_day_time; $i += 86400) {
|
|
|
$date = date('Y-m-d', $i);
|
|
|
$key = date('Y_m', $i);
|
|
|
$create = self::check_create($appointment_template, $date, $list);
|
|
|
if (strtotime($start_date) > $i) $create = false;
|
|
|
if (strtotime($end_date) < $i) $create = false;
|
|
|
$item = [
|
|
|
'date' => $date,
|
|
|
'day' => date('d', $i),
|
|
|
'create' => $create,
|
|
|
];
|
|
|
$date_map[$key][] = $item;
|
|
|
}
|
|
|
$map = [];
|
|
|
foreach ($date_map as $key => $item) {
|
|
|
$map[] = [
|
|
|
'year' => explode('_', $key)[0],
|
|
|
'month' => explode('_', $key)[1],
|
|
|
'list' => self::month_map($item),
|
|
|
];
|
|
|
}
|
|
|
return $map;
|
|
|
}
|
|
|
|
|
|
public function create(Request $request)
|
|
|
{
|
|
|
Login::admin([], [13, 15, 27]);
|
|
|
$hospital_id = $request->post('hospital');
|
|
|
if (Login::$info->hospital != 0) {
|
|
|
if ($hospital_id != Login::$info->hospital) {
|
|
|
Yo::error_echo(100000, ['机构/医院']);
|
|
|
}
|
|
|
}
|
|
|
$id = $request->post('id');
|
|
|
$date_arr = $request->post('date_arr');
|
|
|
$appointment_template = AppointmentTemplate::find($id);
|
|
|
if (!$appointment_template) Yo::error_echo(100000, ['计划模板']);
|
|
|
if (count($date_arr) > 300) Yo::error_echo(200022);
|
|
|
$hospital = Hospital::where('id', $hospital_id)->where('del', 2)->first();
|
|
|
if (!$hospital) Yo::error_echo(100000, ['机构/医院']);
|
|
|
$list = [];
|
|
|
$error = [];
|
|
|
foreach ($date_arr as $date) {
|
|
|
$week = date('w', strtotime($date));
|
|
|
$week = $week == 0 ? 7 : $week;
|
|
|
$appointment = new Appointment();
|
|
|
$appointment->date = $date;
|
|
|
$appointment->week = $week;
|
|
|
$appointment->start_time = $appointment_template->start_time;
|
|
|
$appointment->end_time = $appointment_template->end_time;
|
|
|
$appointment->stop_time = $appointment_template->stop_time;
|
|
|
$appointment->max_count = $appointment_template->max_count;
|
|
|
$appointment->used_count = 0;
|
|
|
$appointment->hospital = $hospital->id;
|
|
|
$appointment->status = 1;
|
|
|
$appointment->save();
|
|
|
if (!!$appointment->id) {
|
|
|
$list[] = $appointment;
|
|
|
} else {
|
|
|
$error[] = $appointment;
|
|
|
}
|
|
|
}
|
|
|
return Yo::echo([
|
|
|
'list' => $list,
|
|
|
'error' => $error,
|
|
|
]);
|
|
|
}
|
|
|
|
|
|
public function create_list(Request $request)
|
|
|
{
|
|
|
Login::admin([], [13, 27]);
|
|
|
$id = $request->post('id');
|
|
|
$start_date = $request->post('start_date');
|
|
|
$end_date = $request->post('end_date');
|
|
|
if (strtotime($start_date) > strtotime($end_date)) Yo::error_echo(200020);
|
|
|
$appointment_template = AppointmentTemplate::find($id);
|
|
|
if (!$appointment_template) Yo::error_echo(100000, ['计划模板']);
|
|
|
$appointment_holiday_list = AppointmentHolidays::where('date', '>=', $start_date)
|
|
|
->where('date', '<=', $end_date)
|
|
|
->get();
|
|
|
$list = [];
|
|
|
foreach ($appointment_holiday_list as $item) {
|
|
|
$list[$item->date] = [
|
|
|
'date' => $item->date,
|
|
|
'type' => $item->type,
|
|
|
];
|
|
|
}
|
|
|
$date_map = self::date_map($start_date, $end_date, $appointment_template, $list);
|
|
|
if (count($date_map) > 12) Yo::error_echo(200021);
|
|
|
return Yo::echo([
|
|
|
'list' => $date_map,
|
|
|
]);
|
|
|
}
|
|
|
|
|
|
public function delete(Request $request)
|
|
|
{
|
|
|
Login::admin([], [15, 27]);
|
|
|
$ids = $request->post('ids');
|
|
|
$appointments_to_delete = Appointment::whereIn('id', $ids)
|
|
|
->where('used_count', '>', 0)
|
|
|
->get();
|
|
|
if (count($appointments_to_delete)) {
|
|
|
return Yo::error_echo(200023);
|
|
|
}
|
|
|
if (Login::$info->id == 1) {
|
|
|
Appointment::whereIn('id', $ids)->update(['del' => 1]);
|
|
|
} else {
|
|
|
Appointment::whereIn('id', $ids)->where('hospital', Login::$info->hospital)->update(['del' => 1]);
|
|
|
}
|
|
|
return Yo::delete_echo($ids);
|
|
|
}
|
|
|
|
|
|
public function change_status(Request $request)
|
|
|
{
|
|
|
Login::admin([], [15, 27]);
|
|
|
$ids = $request->post('ids');
|
|
|
$status = $request->post('status');
|
|
|
if (Login::$info->id == 1) {
|
|
|
Appointment::whereIn('id', $ids)->update(['status' => $status]);
|
|
|
} else {
|
|
|
Appointment::whereIn('id', $ids)->where('hospital', Login::$info->hospital)->update(['status' => $status]);
|
|
|
}
|
|
|
return Yo::update_echo($ids);
|
|
|
}
|
|
|
|
|
|
public function change_count(Request $request)
|
|
|
{
|
|
|
Login::admin([], [15, 27]);
|
|
|
$ids = $request->post('ids');
|
|
|
$count = $request->post('count');
|
|
|
if (Login::$info->id == 1) {
|
|
|
$list = Appointment::whereIn('id', $ids)->get();
|
|
|
} else {
|
|
|
$list = Appointment::whereIn('id', $ids)->where('hospital', Login::$info->hospital)->get();
|
|
|
}
|
|
|
foreach ($list as $item) {
|
|
|
$item->max_count = $count;
|
|
|
$item->save();
|
|
|
}
|
|
|
return Yo::update_echo($ids);
|
|
|
}
|
|
|
|
|
|
public function list(Request $request)
|
|
|
{
|
|
|
Login::admin([], [15, 27]);
|
|
|
$hospital = $request->post('hospital');
|
|
|
if (Login::$info->hospital != 0) {
|
|
|
if ($hospital != Login::$info->hospital) {
|
|
|
Yo::error_echo(100000, ['机构/医院']);
|
|
|
}
|
|
|
}
|
|
|
$start_date = $request->post('start_date');
|
|
|
$end_date = $request->post('end_date');
|
|
|
$status = $request->post('status');
|
|
|
$weeks = $request->post('weeks');
|
|
|
$query = Appointment::select('*')
|
|
|
->selectRaw("IFNULL((select type from appointment_holidays where appointment_holidays.date = appointments.date),0) as date_type")
|
|
|
->where('hospital', $hospital);
|
|
|
if ($status != 0) $query->where('status', '>=', $status);
|
|
|
if (!!$start_date) $query->where('date', '>=', $start_date);
|
|
|
if (!!$end_date) $query->where('date', '<=', $end_date);
|
|
|
if (count($weeks) == 0) $weeks = [1, 2, 3, 4, 5, 6, 7];
|
|
|
$query->whereIn('week', $weeks);
|
|
|
$appointments = $query->where('del', 2)->orderBy('date', 'desc')->paginate(20);
|
|
|
return Yo::echo($appointments);
|
|
|
}
|
|
|
|
|
|
public function mp_list(Request $request)
|
|
|
{
|
|
|
Login::user();
|
|
|
$month = $request->post('month');
|
|
|
$hospital = $request->post('hospital');
|
|
|
$appointments = Appointment::where('hospital', $hospital)
|
|
|
->where('date', 'like', $month . '%')
|
|
|
->where('status', 1)
|
|
|
->where('del', 2)
|
|
|
->orderBy('date')
|
|
|
->get();
|
|
|
$list = [];
|
|
|
foreach ($appointments as $appointment) {
|
|
|
$date = substr($appointment->date, 8, 2);
|
|
|
if (!isset($list[$date])) {
|
|
|
$list[$date] = [
|
|
|
'date' => $appointment->date,
|
|
|
'info' => 0,
|
|
|
'data' => [
|
|
|
'list' => []
|
|
|
],
|
|
|
];
|
|
|
}
|
|
|
$item_time = strtotime($appointment->date . ' ' . $appointment->stop_time);
|
|
|
$start_show = date('H:i', strtotime($appointment->date . ' ' . $appointment->start_time));
|
|
|
$end_show = date('H:i', strtotime($appointment->date . ' ' . $appointment->end_time));
|
|
|
$appointment->start_show = $start_show;
|
|
|
$appointment->end_show = $end_show;
|
|
|
if ($item_time < time()) {
|
|
|
$appointment->used_count = $appointment->max_count;
|
|
|
} else {
|
|
|
$list[$date]['info'] += max($appointment->max_count - $appointment->used_count, 0);
|
|
|
}
|
|
|
$list[$date]['data']['list'][] = $appointment;
|
|
|
}
|
|
|
$l = [];
|
|
|
foreach ($list as $item) {
|
|
|
$l[] = $item;
|
|
|
}
|
|
|
return Yo::echo([
|
|
|
'list' => $l,
|
|
|
]);
|
|
|
}
|
|
|
|
|
|
public function statistics(Request $request)
|
|
|
{
|
|
|
Login::admin([]);
|
|
|
$hospital = $request->post('hospital');
|
|
|
if (Login::$info->hospital != 0) {
|
|
|
if ($hospital != Login::$info->hospital) {
|
|
|
Yo::error_echo(100000, ['机构/医院']);
|
|
|
}
|
|
|
}
|
|
|
$start_date = $request->post('start_date');
|
|
|
$end_date = $request->post('end_date');
|
|
|
|
|
|
// 1. 查询已支付/已完成订单 (status IN 2,4)
|
|
|
$query = UserOrder::where('hospital', $hospital)
|
|
|
->whereIn('status', [2, 4]);
|
|
|
if (!!$start_date) $query->where('created_at', '>=', $start_date);
|
|
|
if (!!$end_date) $query->where('created_at', '<=', $end_date . ' 23:59:59');
|
|
|
$orders = $query->orderBy('id', 'desc')->get();
|
|
|
|
|
|
// 查询已退款订单 (status = 5)
|
|
|
$refund_query = UserOrder::where('hospital', $hospital)
|
|
|
->where('status', 5);
|
|
|
if (!!$start_date) $refund_query->where('refund_time', '>=', $start_date);
|
|
|
if (!!$end_date) $refund_query->where('refund_time', '<=', $end_date . ' 23:59:59');
|
|
|
$refund_orders = $refund_query->get();
|
|
|
|
|
|
// 2. 按类型汇总(个检type=1, 团检type=2)
|
|
|
$charge_amount = round($orders->sum('true_price'), 2);
|
|
|
$refund_amount = round($refund_orders->sum('true_price'), 2);
|
|
|
$total_amount = round($charge_amount - $refund_amount, 2);
|
|
|
|
|
|
$type_summary = [];
|
|
|
foreach ([1 => '个人', 2 => '团检'] as $type_val => $type_name) {
|
|
|
$type_charge = round($orders->where('type', $type_val)->sum('true_price'), 2);
|
|
|
$type_refund = round($refund_orders->where('type', $type_val)->sum('true_price'), 2);
|
|
|
$type_summary[] = [
|
|
|
'name' => $type_name,
|
|
|
'charge' => $type_charge,
|
|
|
'refund' => $type_refund,
|
|
|
'total' => round($type_charge - $type_refund, 2),
|
|
|
];
|
|
|
}
|
|
|
|
|
|
// 3. 收集所有项目Id
|
|
|
$all_item_ids = [];
|
|
|
$order_items = [];
|
|
|
foreach ($orders as $order) {
|
|
|
if (!$order->appointment_info) continue;
|
|
|
$info = json_decode($order->appointment_info, true);
|
|
|
if (!$info || !isset($info['项目列表'])) continue;
|
|
|
$items = [];
|
|
|
foreach ($info['项目列表'] as $item) {
|
|
|
$all_item_ids[] = $item['Id'];
|
|
|
$items[] = $item;
|
|
|
}
|
|
|
$order_items[$order->id] = $items;
|
|
|
}
|
|
|
$all_item_ids = array_values(array_unique($all_item_ids));
|
|
|
|
|
|
// 4. 调用"自选项目查询",获取全部项目 → 科室Id 映射
|
|
|
$item_clinic_map = [];
|
|
|
if (count($all_item_ids) > 0) {
|
|
|
$peis = new PEISApiController();
|
|
|
$items_data = $peis::Post('自选项目查询', $hospital, [
|
|
|
'价格下限' => "0",
|
|
|
'价格上限' => "999999",
|
|
|
"性别" => null,
|
|
|
"妇检" => null,
|
|
|
"套餐Id" => null,
|
|
|
"项目Id列表" => []
|
|
|
])['data'];
|
|
|
foreach ($items_data as $item) {
|
|
|
$item_clinic_map[$item['Id']] = $item['科室Id'];
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 5. 调用"字典查询",获取科室Id → 别名 映射
|
|
|
$clinic_alias_map = [];
|
|
|
if (count($all_item_ids) > 0) {
|
|
|
$peis = new PEISApiController();
|
|
|
$dict_data = $peis::Post('字典查询', $hospital, [
|
|
|
'字典类别' => '科室别名字典'
|
|
|
])['data'];
|
|
|
foreach ($dict_data as $item) {
|
|
|
$clinic_alias_map[$item['Id']] = $item['值'];
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 6. 按别名分组统计收费
|
|
|
$statistics = [];
|
|
|
foreach ($order_items as $order_id => $items) {
|
|
|
foreach ($items as $item) {
|
|
|
$item_id = $item['Id'];
|
|
|
$clinic_id = isset($item_clinic_map[$item_id]) ? $item_clinic_map[$item_id] : null;
|
|
|
$matched = $clinic_id && isset($clinic_alias_map[$clinic_id]);
|
|
|
$alias = $matched ? $clinic_alias_map[$clinic_id] : '未匹配科室';
|
|
|
|
|
|
$price = floatval($item['价格']);
|
|
|
if (isset($item['优惠方式']) && $item['优惠方式'] === '打折') {
|
|
|
$price = $price * floatval($item['优惠值']);
|
|
|
}
|
|
|
|
|
|
$key = $matched ? $alias : '__unmatched__';
|
|
|
if (!isset($statistics[$key])) {
|
|
|
$statistics[$key] = [
|
|
|
'name' => $alias,
|
|
|
'amount' => 0,
|
|
|
'item_names' => [],
|
|
|
];
|
|
|
}
|
|
|
$statistics[$key]['amount'] += $price;
|
|
|
if (!$matched) {
|
|
|
$statistics[$key]['item_names'][] = $item['名称'];
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 格式化金额,未匹配项去重
|
|
|
$categories = [];
|
|
|
foreach ($statistics as $item) {
|
|
|
$item['amount'] = round($item['amount'], 2);
|
|
|
if (isset($item['item_names'])) {
|
|
|
$item['item_names'] = array_values(array_unique($item['item_names']));
|
|
|
}
|
|
|
$categories[] = $item;
|
|
|
}
|
|
|
|
|
|
return Yo::echo([
|
|
|
'type_summary' => $type_summary,
|
|
|
'charge_amount' => $charge_amount,
|
|
|
'refund_amount' => $refund_amount,
|
|
|
'total_amount' => $total_amount,
|
|
|
'total_chinese' => self::amountToChinese($total_amount),
|
|
|
'categories' => $categories,
|
|
|
]);
|
|
|
}
|
|
|
|
|
|
private function amountToChinese($amount)
|
|
|
{
|
|
|
$digits = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'];
|
|
|
$radices = ['', '拾', '佰', '仟'];
|
|
|
$bigRadices = ['', '万', '亿'];
|
|
|
$decimals = ['角', '分'];
|
|
|
|
|
|
$amount = round($amount, 2);
|
|
|
if ($amount == 0) return '零元整';
|
|
|
|
|
|
$amountStr = number_format($amount, 2, '.', '');
|
|
|
$parts = explode('.', $amountStr);
|
|
|
$intPart = $parts[0];
|
|
|
$decPart = $parts[1];
|
|
|
|
|
|
$result = '';
|
|
|
$zeroFlag = false;
|
|
|
$intLen = strlen($intPart);
|
|
|
|
|
|
for ($i = 0; $i < $intLen; $i++) {
|
|
|
$digit = (int)$intPart[$i];
|
|
|
$pos = $intLen - $i - 1;
|
|
|
$radixPos = $pos % 4;
|
|
|
$bigRadixPos = $pos / 4;
|
|
|
|
|
|
if ($digit === 0) {
|
|
|
$zeroFlag = true;
|
|
|
} else {
|
|
|
if ($zeroFlag) {
|
|
|
$result .= '零';
|
|
|
$zeroFlag = false;
|
|
|
}
|
|
|
$result .= $digits[$digit] . $radices[$radixPos];
|
|
|
}
|
|
|
|
|
|
if ($radixPos === 0 && $pos > 0) {
|
|
|
if (!$zeroFlag || $pos >= 8) {
|
|
|
$result .= $bigRadices[(int)$bigRadixPos];
|
|
|
}
|
|
|
$zeroFlag = false;
|
|
|
}
|
|
|
}
|
|
|
$result .= '元';
|
|
|
|
|
|
if ($decPart === '00') {
|
|
|
$result .= '整';
|
|
|
} else {
|
|
|
$jiao = (int)$decPart[0];
|
|
|
$fen = (int)$decPart[1];
|
|
|
if ($jiao > 0) {
|
|
|
$result .= $digits[$jiao] . '角';
|
|
|
} elseif ($jiao === 0 && $fen > 0) {
|
|
|
$result .= '零';
|
|
|
}
|
|
|
if ($fen > 0) {
|
|
|
$result .= $digits[$fen] . '分';
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return $result;
|
|
|
}
|
|
|
}
|