Files
zyt/server/app/adminapi/logic/doctor/RosterLogic.php
T
2026-05-11 17:49:38 +08:00

283 lines
8.4 KiB
PHP
Executable File
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\adminapi\logic\doctor;
use app\common\logic\BaseLogic;
use app\common\model\doctor\Roster;
use app\common\service\doctor\RosterSegmentService;
use think\facade\Db;
/**
* 医生排班逻辑
* Class RosterLogic
* @package app\adminapi\logic\doctor
*/
class RosterLogic extends BaseLogic
{
/**
* 组装单条排班数据(period 缺省为 segment
*/
protected static function buildRowData(array $params): array
{
$period = $params['period'] ?? '';
if (!in_array($period, ['morning', 'afternoon', 'night', 'segment'], true)) {
$period = 'segment';
}
$start = trim((string) ($params['start_time'] ?? ''));
$end = trim((string) ($params['end_time'] ?? ''));
$status = (int) $params['status'];
$slotMinutes = RosterSegmentService::normalizeSlotMinutes($params['slot_minutes'] ?? 15);
if ($status === 1) {
if ($start === '' || $end === '') {
throw new \InvalidArgumentException('出诊须填写接诊开始与结束时间');
}
if ($start >= $end) {
throw new \InvalidArgumentException('结束时间须晚于开始时间');
}
} else {
if ($start === '' || $end === '') {
throw new \InvalidArgumentException('请填写时段开始与结束时间');
}
if ($start >= $end) {
throw new \InvalidArgumentException('结束时间须晚于开始时间');
}
}
$shiftType = $params['shift_type'] ?? '';
if ($shiftType !== '' && !in_array($shiftType, ['day', 'night'], true)) {
$shiftType = '';
}
$quota = (int) ($params['quota'] ?? 0);
if ($status !== 1) {
$quota = 0;
}
return [
'doctor_id' => (int) $params['doctor_id'],
'date' => $params['date'],
'period' => $period,
'start_time' => $start,
'end_time' => $end,
'shift_type' => $shiftType !== '' ? $shiftType : null,
'slot_minutes' => $slotMinutes,
'status' => $status,
'quota' => $quota,
'max_patients' => $status === 1 ? (int) ($params['max_patients'] ?? 0) : 0,
'remark' => (string) ($params['remark'] ?? ''),
];
}
/**
* 是否存在相同医生、日期、起止时间的记录(排除指定 id)
*/
protected static function duplicateExists(int $doctorId, string $date, string $start, string $end, ?int $excludeId = null): bool
{
$q = Roster::where([
['doctor_id', '=', $doctorId],
['date', '=', $date],
['start_time', '=', $start],
['end_time', '=', $end],
]);
if ($excludeId) {
$q->where('id', '<>', $excludeId);
}
return (bool) $q->find();
}
/**
* @notes 保存排班
* @param array $params
* @return array|bool
*/
public static function save(array $params)
{
try {
$data = self::buildRowData($params);
if (self::duplicateExists($data['doctor_id'], $data['date'], $data['start_time'], $data['end_time'], !empty($params['id']) ? (int) $params['id'] : null)) {
self::setError('该医生在同一天已存在相同的接诊时段');
return false;
}
if (!empty($params['id'])) {
$data['update_time'] = time();
Roster::where('id', (int) $params['id'])->update($data);
return ['id' => (int) $params['id']];
}
$data['create_time'] = time();
$data['update_time'] = time();
$roster = Roster::create($data);
return ['id' => $roster->id];
} catch (\InvalidArgumentException $e) {
self::setError($e->getMessage());
return false;
} catch (\Exception $e) {
self::setError($e->getMessage());
return false;
}
}
/**
* @notes 删除排班
* @param array $params
* @return bool
*/
public static function delete(array $params)
{
try {
Roster::destroy($params['id']);
return true;
} catch (\Exception $e) {
self::setError($e->getMessage());
return false;
}
}
/**
* @notes 排班详情
* @param array $params
* @return array
*/
public static function detail(array $params)
{
return Roster::findOrEmpty($params['id'])->toArray();
}
/**
* @notes 批量保存排班
* @param array $params
* @return array|bool
*/
public static function batchSave(array $params)
{
try {
Db::startTrans();
$successCount = 0;
$updateCount = 0;
$createCount = 0;
foreach ($params['rosters'] as $roster) {
$data = self::buildRowData($roster);
$exists = Roster::where([
['doctor_id', '=', $data['doctor_id']],
['date', '=', $data['date']],
['start_time', '=', $data['start_time']],
['end_time', '=', $data['end_time']],
])->find();
if ($exists) {
$data['update_time'] = time();
$exists->save($data);
++$updateCount;
} else {
$data['create_time'] = time();
$data['update_time'] = time();
Roster::create($data);
++$createCount;
}
++$successCount;
}
Db::commit();
return [
'success_count' => $successCount,
'create_count' => $createCount,
'update_count' => $updateCount,
];
} catch (\InvalidArgumentException $e) {
Db::rollback();
self::setError($e->getMessage());
return false;
} catch (\Exception $e) {
Db::rollback();
self::setError($e->getMessage());
return false;
}
}
/**
* @notes 复制排班
* @param array $params
* @return bool
*/
public static function copy(array $params)
{
try {
Db::startTrans();
$where = [
['date', 'between', [$params['source_start_date'], $params['source_end_date']]],
];
if (isset($params['doctor_id']) && $params['doctor_id']) {
$where[] = ['doctor_id', '=', $params['doctor_id']];
}
$sourceRosters = Roster::where($where)->select();
$targetDays = (strtotime($params['target_start_date']) - strtotime($params['source_start_date'])) / 86400;
foreach ($sourceRosters as $roster) {
$newDate = date('Y-m-d', strtotime($roster->date) + ($targetDays * 86400));
$data = [
'doctor_id' => $roster->doctor_id,
'date' => $newDate,
'period' => $roster->period,
'start_time' => $roster->start_time,
'end_time' => $roster->end_time,
'shift_type' => $roster->shift_type,
'slot_minutes' => $roster->slot_minutes ?: 15,
'status' => $roster->status,
'quota' => $roster->quota,
'max_patients' => $roster->max_patients,
'remark' => $roster->remark,
'create_time' => time(),
'update_time' => time(),
];
if (empty($data['start_time']) || empty($data['end_time'])) {
continue;
}
$dup = Roster::where([
['doctor_id', '=', $data['doctor_id']],
['date', '=', $data['date']],
['start_time', '=', $data['start_time']],
['end_time', '=', $data['end_time']],
])->find();
if (!$dup) {
Roster::create($data);
}
}
Db::commit();
return true;
} catch (\Exception $e) {
Db::rollback();
self::setError($e->getMessage());
return false;
}
}
}