feat: 근무/출퇴근 설정 및 현장 관리 API 구현
- 근무 설정 API (GET/PUT /settings/work)
- 근무유형, 소정근로시간, 연장근로시간, 근무요일, 출퇴근시간, 휴게시간
- 출퇴근 설정 API (GET/PUT /settings/attendance)
- GPS 출퇴근, 허용 반경, 본사 위치 설정
- 현장 관리 API (CRUD /sites)
- 현장 등록/수정/삭제, 활성화된 현장 목록(셀렉트박스용)
- GPS 좌표 기반 위치 관리
마이그레이션: work_settings, attendance_settings, sites 테이블
모델: WorkSetting, AttendanceSetting, Site (BelongsToTenant, SoftDeletes)
서비스: WorkSettingService, SiteService
Swagger 문서 및 i18n 메시지 키 추가
2025-12-17 20:46:37 +09:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace App\Models\Tenants;
|
|
|
|
|
|
|
|
|
|
use App\Traits\BelongsToTenant;
|
|
|
|
|
use Illuminate\Database\Eloquent\Model;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 근무 설정 모델
|
|
|
|
|
*
|
|
|
|
|
* @property int $id
|
|
|
|
|
* @property int $tenant_id
|
|
|
|
|
* @property string $work_type
|
|
|
|
|
* @property int $standard_hours
|
|
|
|
|
* @property int $overtime_hours
|
|
|
|
|
* @property int $overtime_limit
|
|
|
|
|
* @property array|null $work_days
|
|
|
|
|
* @property string $start_time
|
|
|
|
|
* @property string $end_time
|
|
|
|
|
* @property int $break_minutes
|
|
|
|
|
* @property string|null $break_start
|
|
|
|
|
* @property string|null $break_end
|
|
|
|
|
*/
|
|
|
|
|
class WorkSetting extends Model
|
|
|
|
|
{
|
|
|
|
|
use BelongsToTenant;
|
|
|
|
|
|
|
|
|
|
protected $table = 'work_settings';
|
|
|
|
|
|
|
|
|
|
protected $fillable = [
|
|
|
|
|
'tenant_id',
|
|
|
|
|
'work_type',
|
|
|
|
|
'standard_hours',
|
|
|
|
|
'overtime_hours',
|
|
|
|
|
'overtime_limit',
|
|
|
|
|
'work_days',
|
|
|
|
|
'start_time',
|
|
|
|
|
'end_time',
|
|
|
|
|
'break_minutes',
|
|
|
|
|
'break_start',
|
|
|
|
|
'break_end',
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
protected $casts = [
|
2025-12-30 21:42:20 +09:00
|
|
|
// work_days는 Attribute accessor에서 처리
|
feat: 근무/출퇴근 설정 및 현장 관리 API 구현
- 근무 설정 API (GET/PUT /settings/work)
- 근무유형, 소정근로시간, 연장근로시간, 근무요일, 출퇴근시간, 휴게시간
- 출퇴근 설정 API (GET/PUT /settings/attendance)
- GPS 출퇴근, 허용 반경, 본사 위치 설정
- 현장 관리 API (CRUD /sites)
- 현장 등록/수정/삭제, 활성화된 현장 목록(셀렉트박스용)
- GPS 좌표 기반 위치 관리
마이그레이션: work_settings, attendance_settings, sites 테이블
모델: WorkSetting, AttendanceSetting, Site (BelongsToTenant, SoftDeletes)
서비스: WorkSettingService, SiteService
Swagger 문서 및 i18n 메시지 키 추가
2025-12-17 20:46:37 +09:00
|
|
|
'standard_hours' => 'integer',
|
|
|
|
|
'overtime_hours' => 'integer',
|
|
|
|
|
'overtime_limit' => 'integer',
|
|
|
|
|
'break_minutes' => 'integer',
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
protected $attributes = [
|
|
|
|
|
'work_type' => 'fixed',
|
|
|
|
|
'standard_hours' => 40,
|
|
|
|
|
'overtime_hours' => 12,
|
|
|
|
|
'overtime_limit' => 52,
|
|
|
|
|
'start_time' => '09:00:00',
|
|
|
|
|
'end_time' => '18:00:00',
|
|
|
|
|
'break_minutes' => 60,
|
|
|
|
|
'break_start' => '12:00:00',
|
|
|
|
|
'break_end' => '13:00:00',
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
// =========================================================================
|
|
|
|
|
// 상수 정의
|
|
|
|
|
// =========================================================================
|
|
|
|
|
|
|
|
|
|
public const TYPE_FIXED = 'fixed'; // 고정 근무
|
|
|
|
|
|
|
|
|
|
public const TYPE_FLEXIBLE = 'flexible'; // 유연 근무
|
|
|
|
|
|
|
|
|
|
public const TYPE_CUSTOM = 'custom'; // 커스텀 근무
|
|
|
|
|
|
|
|
|
|
public const WORK_TYPES = [
|
|
|
|
|
self::TYPE_FIXED,
|
|
|
|
|
self::TYPE_FLEXIBLE,
|
|
|
|
|
self::TYPE_CUSTOM,
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
public const DEFAULT_WORK_DAYS = ['mon', 'tue', 'wed', 'thu', 'fri'];
|
|
|
|
|
|
2025-12-30 21:42:20 +09:00
|
|
|
/**
|
|
|
|
|
* 숫자 → 요일 문자열 매핑
|
|
|
|
|
*/
|
|
|
|
|
public const DAY_INDEX_MAP = [
|
|
|
|
|
1 => 'mon',
|
|
|
|
|
2 => 'tue',
|
|
|
|
|
3 => 'wed',
|
|
|
|
|
4 => 'thu',
|
|
|
|
|
5 => 'fri',
|
|
|
|
|
6 => 'sat',
|
|
|
|
|
7 => 'sun',
|
|
|
|
|
0 => 'sun', // 일요일이 0인 경우도 처리
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
// =========================================================================
|
|
|
|
|
// Accessors & Mutators
|
|
|
|
|
// =========================================================================
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* work_days 조회 시 숫자를 문자열로 변환
|
|
|
|
|
*/
|
|
|
|
|
protected function workDays(): \Illuminate\Database\Eloquent\Casts\Attribute
|
|
|
|
|
{
|
|
|
|
|
return \Illuminate\Database\Eloquent\Casts\Attribute::make(
|
|
|
|
|
get: function ($value) {
|
|
|
|
|
$days = is_string($value) ? json_decode($value, true) : $value;
|
|
|
|
|
|
|
|
|
|
if (! is_array($days)) {
|
|
|
|
|
return self::DEFAULT_WORK_DAYS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 숫자가 포함된 경우 문자열로 변환
|
|
|
|
|
return array_values(array_unique(array_map(function ($day) {
|
|
|
|
|
if (is_int($day) || is_numeric($day)) {
|
|
|
|
|
return self::DAY_INDEX_MAP[(int) $day] ?? 'mon';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $day;
|
|
|
|
|
}, $days)));
|
|
|
|
|
},
|
|
|
|
|
set: function ($value) {
|
|
|
|
|
if (! is_array($value)) {
|
|
|
|
|
return json_encode(self::DEFAULT_WORK_DAYS);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 항상 문자열 배열로 저장
|
|
|
|
|
$days = array_values(array_unique(array_map(function ($day) {
|
|
|
|
|
if (is_int($day) || is_numeric($day)) {
|
|
|
|
|
return self::DAY_INDEX_MAP[(int) $day] ?? 'mon';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $day;
|
|
|
|
|
}, $value)));
|
|
|
|
|
|
|
|
|
|
return json_encode($days);
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
feat: 근무/출퇴근 설정 및 현장 관리 API 구현
- 근무 설정 API (GET/PUT /settings/work)
- 근무유형, 소정근로시간, 연장근로시간, 근무요일, 출퇴근시간, 휴게시간
- 출퇴근 설정 API (GET/PUT /settings/attendance)
- GPS 출퇴근, 허용 반경, 본사 위치 설정
- 현장 관리 API (CRUD /sites)
- 현장 등록/수정/삭제, 활성화된 현장 목록(셀렉트박스용)
- GPS 좌표 기반 위치 관리
마이그레이션: work_settings, attendance_settings, sites 테이블
모델: WorkSetting, AttendanceSetting, Site (BelongsToTenant, SoftDeletes)
서비스: WorkSettingService, SiteService
Swagger 문서 및 i18n 메시지 키 추가
2025-12-17 20:46:37 +09:00
|
|
|
// =========================================================================
|
|
|
|
|
// 헬퍼 메서드
|
|
|
|
|
// =========================================================================
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 근무 유형 라벨
|
|
|
|
|
*/
|
|
|
|
|
public function getWorkTypeLabelAttribute(): string
|
|
|
|
|
{
|
|
|
|
|
return match ($this->work_type) {
|
|
|
|
|
self::TYPE_FIXED => '고정근무',
|
|
|
|
|
self::TYPE_FLEXIBLE => '유연근무',
|
|
|
|
|
self::TYPE_CUSTOM => '커스텀',
|
|
|
|
|
default => $this->work_type,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 일일 근무시간 계산 (분)
|
|
|
|
|
*/
|
|
|
|
|
public function getDailyWorkMinutesAttribute(): int
|
|
|
|
|
{
|
|
|
|
|
$start = strtotime($this->start_time);
|
|
|
|
|
$end = strtotime($this->end_time);
|
|
|
|
|
$totalMinutes = ($end - $start) / 60;
|
|
|
|
|
|
|
|
|
|
return (int) ($totalMinutes - $this->break_minutes);
|
|
|
|
|
}
|
|
|
|
|
}
|