|
|
<?php
|
|
|
|
|
|
namespace App\Http\Controllers\API\H5;
|
|
|
|
|
|
use App\Http\Controllers\Controller;
|
|
|
use Illuminate\Http\Request;
|
|
|
use App\Lib\Rs;
|
|
|
use App\Services\PatientAuthService;
|
|
|
use App\Services\PlanService;
|
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
|
|
class PlanController extends Controller
|
|
|
{
|
|
|
private PatientAuthService $patientAuthService;
|
|
|
private PlanService $planService;
|
|
|
|
|
|
public function __construct(PatientAuthService $patientAuthService, PlanService $planService)
|
|
|
{
|
|
|
$this->patientAuthService = $patientAuthService;
|
|
|
$this->planService = $planService;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 获取号源日历(按月查询)
|
|
|
* POST /api/h5/plan/calendar
|
|
|
*/
|
|
|
public function calendar(Request $request)
|
|
|
{
|
|
|
$payload = $request->attributes->get('payload');
|
|
|
$idCardNo = $this->patientAuthService->getPatientIdCardNo($payload);
|
|
|
|
|
|
$examApplicationIds = $request->input('exam_application_ids', []);
|
|
|
$year = $request->input('year', date('Y'));
|
|
|
$month = $request->input('month', date('n'));
|
|
|
$channelId = (int)$request->input('channel_id', 3);
|
|
|
|
|
|
if (empty($examApplicationIds) || !is_array($examApplicationIds)) {
|
|
|
return Rs::error('请选择检查项目');
|
|
|
}
|
|
|
|
|
|
$count = DB::table('exam_application')
|
|
|
->whereIn('id', $examApplicationIds)
|
|
|
->where('patient_id_card_no', $idCardNo)
|
|
|
->count();
|
|
|
|
|
|
if ($count != count($examApplicationIds)) {
|
|
|
return Rs::error('申请单校验失败');
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
$firstDayOfMonth = strtotime(sprintf('%04d-%02d-01', $year, $month));
|
|
|
$firstDayOfWeek = date('w', $firstDayOfMonth);
|
|
|
$startDate = date('Y-m-d', strtotime("-{$firstDayOfWeek} days", $firstDayOfMonth));
|
|
|
|
|
|
$daysInMonth = cal_days_in_month(CAL_GREGORIAN, $month, $year);
|
|
|
$lastDayOfWeek = date('w', strtotime(sprintf('%04d-%02d-%d', $year, $month, $daysInMonth)));
|
|
|
$totalDays = $firstDayOfWeek + $daysInMonth + (6 - $lastDayOfWeek);
|
|
|
$totalRows = ceil($totalDays / 7);
|
|
|
|
|
|
$today = date('Y-m-d');
|
|
|
$calendarDates = [];
|
|
|
$currentDate = $startDate;
|
|
|
for ($i = 0; $i < $totalRows * 7; $i++) {
|
|
|
if ($currentDate >= $today) {
|
|
|
$calendarDates[] = $currentDate;
|
|
|
}
|
|
|
$currentDate = date('Y-m-d', strtotime('+1 day', strtotime($currentDate)));
|
|
|
}
|
|
|
|
|
|
if (empty($calendarDates)) {
|
|
|
return Rs::success(['resources' => []]);
|
|
|
}
|
|
|
|
|
|
$planData = $this->planService->queryPlanBatchesData(
|
|
|
$examApplicationIds, $channelId, '', 0, $calendarDates
|
|
|
);
|
|
|
|
|
|
$planBatches = $planData['planBatches'];
|
|
|
$quotaByBatch = $planData['quotaByBatch'];
|
|
|
|
|
|
if ($planBatches->isEmpty()) {
|
|
|
return Rs::success(['resources' => []]);
|
|
|
}
|
|
|
|
|
|
$resourcesData = [];
|
|
|
$batchesByResource = $planBatches->groupBy('resource_id');
|
|
|
|
|
|
foreach ($batchesByResource as $resourceId => $batches) {
|
|
|
$resource = $batches->first();
|
|
|
$batchesByDate = $batches->groupBy('plan_date');
|
|
|
|
|
|
$datesData = [];
|
|
|
foreach ($calendarDates as $date) {
|
|
|
if (!isset($batchesByDate[$date])) {
|
|
|
$datesData[$date] = [
|
|
|
'date' => $date,
|
|
|
'total_count' => 0,
|
|
|
'available_count' => 0
|
|
|
];
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
$totalCount = 0;
|
|
|
$availableCount = 0;
|
|
|
|
|
|
foreach ($batchesByDate[$date] as $batch) {
|
|
|
$remaining = $this->planService->calculateRemainingQuota(
|
|
|
$batch,
|
|
|
$channelId,
|
|
|
$quotaByBatch[$batch->batch_id]['channel'] ?? null,
|
|
|
$quotaByBatch[$batch->batch_id]['public'] ?? null,
|
|
|
1
|
|
|
);
|
|
|
|
|
|
$quotas = $quotaByBatch[$batch->batch_id] ?? ['public' => null, 'channel' => null];
|
|
|
$publicQuota = $quotas['public'];
|
|
|
$channelQuota = $quotas['channel'];
|
|
|
$enableChannelQuota = ($batch->enable_channel_quota ?? 0) == 1;
|
|
|
|
|
|
if (!$enableChannelQuota) {
|
|
|
if (!$publicQuota) continue;
|
|
|
$totalQuota = $publicQuota->total_quota;
|
|
|
$usedQuota = $publicQuota->used_quota;
|
|
|
$lockedQuota = $publicQuota->locked_quota ?? 0;
|
|
|
} else {
|
|
|
if (!$channelQuota) continue;
|
|
|
$totalQuota = $channelQuota->total_quota;
|
|
|
$usedQuota = $channelQuota->used_quota;
|
|
|
$lockedQuota = $channelQuota->locked_quota ?? 0;
|
|
|
$allowOveruse = $channelQuota->allow_overuse_public_pool ?? 0;
|
|
|
if ($allowOveruse && $publicQuota) {
|
|
|
$totalQuota += $publicQuota->total_quota;
|
|
|
$usedQuota += $publicQuota->used_quota;
|
|
|
$lockedQuota += $publicQuota->locked_quota ?? 0;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
$totalCount += $totalQuota;
|
|
|
$availableCount += max(0, $totalQuota - $usedQuota - $lockedQuota);
|
|
|
}
|
|
|
|
|
|
$datesData[$date] = [
|
|
|
'date' => $date,
|
|
|
'total_count' => $totalCount,
|
|
|
'available_count' => $availableCount
|
|
|
];
|
|
|
}
|
|
|
|
|
|
$resourcesData[] = [
|
|
|
'room_id' => $resourceId,
|
|
|
'room_name' => $resource->resource_name,
|
|
|
'slot_data' => array_values($datesData)
|
|
|
];
|
|
|
}
|
|
|
|
|
|
return Rs::success(['resources' => $resourcesData]);
|
|
|
} catch (\Exception $e) {
|
|
|
return Rs::error('获取号源日历失败:' . $e->getMessage());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 获取可用号源(选定日期后)
|
|
|
* POST /api/h5/plan/available
|
|
|
*/
|
|
|
public function available(Request $request)
|
|
|
{
|
|
|
$payload = $request->attributes->get('payload');
|
|
|
$idCardNo = $this->patientAuthService->getPatientIdCardNo($payload);
|
|
|
|
|
|
$examApplicationIds = $request->input('exam_application_ids', []);
|
|
|
$startDate = $request->input('start_date', date('Y-m-d'));
|
|
|
$channelId = (int)$request->input('channel_id', 3); // 默认微信,自助机传4
|
|
|
|
|
|
if (empty($examApplicationIds) || !is_array($examApplicationIds)) {
|
|
|
return Rs::error('请选择检查项目');
|
|
|
}
|
|
|
|
|
|
// 校验申请单属于当前患者
|
|
|
$count = DB::table('exam_application')
|
|
|
->whereIn('id', $examApplicationIds)
|
|
|
->where('patient_id_card_no', $idCardNo)
|
|
|
->count();
|
|
|
|
|
|
if ($count != count($examApplicationIds)) {
|
|
|
return Rs::error('申请单校验失败');
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
$planData = $this->planService->queryPlanBatchesData($examApplicationIds, $channelId, $startDate, 1);
|
|
|
|
|
|
$planBatches = $planData['planBatches'];
|
|
|
$quotaByBatch = $planData['quotaByBatch'];
|
|
|
$totalUseSeats = $planData['totalUseSeats'];
|
|
|
|
|
|
$now = now();
|
|
|
$currentDate = $now->format('Y-m-d');
|
|
|
|
|
|
$resourcesData = [];
|
|
|
$batchesByResource = $planBatches->groupBy('resource_id');
|
|
|
|
|
|
foreach ($batchesByResource as $resourceId => $batches) {
|
|
|
$resource = $batches->first();
|
|
|
$slotMode = $resource->slot_mode;
|
|
|
$periods = [];
|
|
|
|
|
|
foreach ($batches as $batch) {
|
|
|
$isPastCutoff = ($batch->plan_date === $currentDate) &&
|
|
|
$now->gt(\Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $batch->plan_date . ' ' . $batch->cutoff_time));
|
|
|
|
|
|
$quotas = $quotaByBatch[$batch->batch_id] ?? ['public' => null, 'channel' => null];
|
|
|
$publicQuota = $quotas['public'];
|
|
|
$channelQuota = $quotas['channel'];
|
|
|
|
|
|
if ($slotMode == 1) {
|
|
|
// 时间段模式
|
|
|
if (($batch->enable_channel_quota ?? 0) == 0) {
|
|
|
if (!$publicQuota) continue;
|
|
|
$effectiveQuota = $publicQuota;
|
|
|
$allowOveruse = 0;
|
|
|
} else {
|
|
|
if (!$channelQuota) continue;
|
|
|
$effectiveQuota = $channelQuota;
|
|
|
$allowOveruse = $channelQuota->allow_overuse_public_pool ?? 0;
|
|
|
}
|
|
|
|
|
|
$totalQuota = $effectiveQuota->total_quota;
|
|
|
$usedQuota = $effectiveQuota->used_quota;
|
|
|
$lockedQuota = $effectiveQuota->locked_quota ?? 0;
|
|
|
|
|
|
if ($allowOveruse && $publicQuota && ($batch->enable_channel_quota ?? 0) != 0) {
|
|
|
$totalQuota += $publicQuota->total_quota;
|
|
|
$usedQuota += $publicQuota->used_quota;
|
|
|
$lockedQuota += $publicQuota->locked_quota ?? 0;
|
|
|
}
|
|
|
|
|
|
$remainCount = max(0, $totalQuota - $usedQuota - $lockedQuota);
|
|
|
$enable = $remainCount >= $totalUseSeats && !$isPastCutoff;
|
|
|
|
|
|
$planRecord = DB::table('plan')
|
|
|
->where('batch_id', $batch->batch_id)
|
|
|
->where('deleted', 0)
|
|
|
->select('id')
|
|
|
->first();
|
|
|
|
|
|
$periods[] = [
|
|
|
'period_id' => $batch->batch_id,
|
|
|
'time_range' => substr($batch->start_time, 0, 5) . '-' . substr($batch->end_time, 0, 5),
|
|
|
'plan_id' => $planRecord ? $planRecord->id : null,
|
|
|
'remain_count' => $remainCount,
|
|
|
'total_count' => $totalQuota,
|
|
|
'enable' => $enable
|
|
|
];
|
|
|
} else {
|
|
|
// 时间点模式
|
|
|
$enableChannelQuota = ($batch->enable_channel_quota ?? 0) == 1;
|
|
|
if ($enableChannelQuota && !$channelQuota) continue;
|
|
|
|
|
|
$overallTotal = 0;
|
|
|
$overallUsed = 0;
|
|
|
$hasQuota = false;
|
|
|
|
|
|
if (!$enableChannelQuota) {
|
|
|
if ($publicQuota) {
|
|
|
$overallTotal = $publicQuota->total_quota;
|
|
|
$overallUsed = $publicQuota->used_quota;
|
|
|
$hasQuota = true;
|
|
|
}
|
|
|
} else {
|
|
|
if ($channelQuota) {
|
|
|
$overallTotal = $channelQuota->total_quota;
|
|
|
$overallUsed = $channelQuota->used_quota;
|
|
|
$allowOveruse = $channelQuota->allow_overuse_public_pool ?? 0;
|
|
|
if ($allowOveruse && $publicQuota) {
|
|
|
$overallTotal += $publicQuota->total_quota;
|
|
|
$overallUsed += $publicQuota->used_quota;
|
|
|
}
|
|
|
$hasQuota = true;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
$timePoints = DB::table('plan')
|
|
|
->where('batch_id', $batch->batch_id)
|
|
|
->where(['status' => 1, 'deleted' => 0])
|
|
|
->select('id', 'start_time', 'end_time', 'total_quota', 'used_quota', 'locked_quota')
|
|
|
->orderBy('start_time')
|
|
|
->get();
|
|
|
|
|
|
if ($timePoints->isEmpty()) continue;
|
|
|
|
|
|
$slots = [];
|
|
|
foreach ($timePoints as $tp) {
|
|
|
$isTimeExpired = false;
|
|
|
if ($batch->plan_date === $currentDate) {
|
|
|
$tpStartTime = \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $batch->plan_date . ' ' . $tp->start_time);
|
|
|
$isTimeExpired = $now->gt($tpStartTime);
|
|
|
}
|
|
|
|
|
|
if (!$hasQuota || ($overallTotal - $overallUsed) <= 0) {
|
|
|
$slots[] = ['id' => $tp->id, 'time' => substr($tp->start_time, 0, 5), 'enable' => false, 'remain_count' => 0, 'total_count' => $tp->total_quota];
|
|
|
} else {
|
|
|
$available = $tp->total_quota - $tp->used_quota - ($tp->locked_quota ?? 0);
|
|
|
$slots[] = ['id' => $tp->id, 'time' => substr($tp->start_time, 0, 5), 'enable' => $available > 0 && !$isPastCutoff && !$isTimeExpired, 'remain_count' => max(0, $available), 'total_count' => $tp->total_quota];
|
|
|
}
|
|
|
}
|
|
|
|
|
|
$periods[] = [
|
|
|
'period_id' => $batch->batch_id,
|
|
|
'time_range' => substr($batch->start_time, 0, 5) . '-' . substr($batch->end_time, 0, 5),
|
|
|
'plan_id' => null,
|
|
|
'slots' => $slots
|
|
|
];
|
|
|
}
|
|
|
}
|
|
|
|
|
|
$resourcesData[] = [
|
|
|
'room_id' => $resourceId,
|
|
|
'room_name' => $resource->resource_name,
|
|
|
'slot_mode' => $slotMode,
|
|
|
'periods' => $periods
|
|
|
];
|
|
|
}
|
|
|
|
|
|
return Rs::success(['resources' => $resourcesData]);
|
|
|
} catch (\Exception $e) {
|
|
|
return Rs::error('获取可用号源失败:' . $e->getMessage());
|
|
|
}
|
|
|
}
|
|
|
}
|