feat: [hr] 사업소득자관리 메뉴 신설
- BusinessIncomeEarner 모델 생성 (worker_type 글로벌 스코프) - Employee 모델에 worker_type 글로벌 스코프 추가 (기존 사원 격리) - BusinessIncomeEarnerService 생성 (등록/수정/삭제/조회) - Web/API 컨트롤러 생성 (CRUD + 파일 업로드) - 라우트 추가 (web.php, api.php) - View 5개 생성 (index, create, show, edit, partials/table) - 사업장등록정보 6개 필드 (사업자등록번호, 상호, 대표자명, 업태, 종목, 소재지)
This commit is contained in:
236
app/Models/HR/BusinessIncomeEarner.php
Normal file
236
app/Models/HR/BusinessIncomeEarner.php
Normal file
@@ -0,0 +1,236 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\HR;
|
||||
|
||||
use App\Models\Tenants\Department;
|
||||
use App\Models\User;
|
||||
use App\Traits\ModelTrait;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class BusinessIncomeEarner extends Model
|
||||
{
|
||||
use ModelTrait;
|
||||
|
||||
protected $table = 'tenant_user_profiles';
|
||||
|
||||
protected $fillable = [
|
||||
'tenant_id',
|
||||
'user_id',
|
||||
'department_id',
|
||||
'position_key',
|
||||
'job_title_key',
|
||||
'work_location_key',
|
||||
'employment_type_key',
|
||||
'employee_status',
|
||||
'worker_type',
|
||||
'manager_user_id',
|
||||
'json_extra',
|
||||
'profile_photo_path',
|
||||
'display_name',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'json_extra' => 'array',
|
||||
'tenant_id' => 'int',
|
||||
'user_id' => 'int',
|
||||
'department_id' => 'int',
|
||||
'manager_user_id' => 'int',
|
||||
];
|
||||
|
||||
protected $appends = [
|
||||
'hire_date',
|
||||
'resign_date',
|
||||
'position_label',
|
||||
'job_title_label',
|
||||
];
|
||||
|
||||
// =========================================================================
|
||||
// 글로벌 스코프 + 이벤트
|
||||
// =========================================================================
|
||||
|
||||
protected static function booted(): void
|
||||
{
|
||||
static::addGlobalScope('business_income', function (Builder $builder) {
|
||||
$builder->where('worker_type', 'business_income');
|
||||
});
|
||||
|
||||
static::creating(function (self $model) {
|
||||
$model->worker_type = 'business_income';
|
||||
});
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 관계 정의
|
||||
// =========================================================================
|
||||
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'user_id');
|
||||
}
|
||||
|
||||
public function department(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Department::class, 'department_id');
|
||||
}
|
||||
|
||||
public function manager(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'manager_user_id');
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// json_extra Accessor (Employee 동일)
|
||||
// =========================================================================
|
||||
|
||||
public function getHireDateAttribute(): ?string
|
||||
{
|
||||
return $this->json_extra['hire_date'] ?? null;
|
||||
}
|
||||
|
||||
public function getResignDateAttribute(): ?string
|
||||
{
|
||||
return $this->json_extra['resign_date'] ?? null;
|
||||
}
|
||||
|
||||
public function getAddressAttribute(): ?string
|
||||
{
|
||||
return $this->json_extra['address'] ?? null;
|
||||
}
|
||||
|
||||
public function getEmergencyContactAttribute(): ?string
|
||||
{
|
||||
return $this->json_extra['emergency_contact'] ?? null;
|
||||
}
|
||||
|
||||
public function getResidentNumberAttribute(): ?string
|
||||
{
|
||||
return $this->json_extra['resident_number'] ?? null;
|
||||
}
|
||||
|
||||
public function getBankAccountAttribute(): ?array
|
||||
{
|
||||
return $this->json_extra['bank_account'] ?? null;
|
||||
}
|
||||
|
||||
public function getDependentsAttribute(): array
|
||||
{
|
||||
return $this->json_extra['dependents'] ?? [];
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 사업장등록정보 Accessor (json_extra에서 읽기)
|
||||
// =========================================================================
|
||||
|
||||
public function getBusinessRegistrationNumberAttribute(): ?string
|
||||
{
|
||||
return $this->json_extra['business_registration_number'] ?? null;
|
||||
}
|
||||
|
||||
public function getBusinessNameAttribute(): ?string
|
||||
{
|
||||
return $this->json_extra['business_name'] ?? null;
|
||||
}
|
||||
|
||||
public function getBusinessRepresentativeAttribute(): ?string
|
||||
{
|
||||
return $this->json_extra['business_representative'] ?? null;
|
||||
}
|
||||
|
||||
public function getBusinessTypeAttribute(): ?string
|
||||
{
|
||||
return $this->json_extra['business_type'] ?? null;
|
||||
}
|
||||
|
||||
public function getBusinessCategoryAttribute(): ?string
|
||||
{
|
||||
return $this->json_extra['business_category'] ?? null;
|
||||
}
|
||||
|
||||
public function getBusinessAddressAttribute(): ?string
|
||||
{
|
||||
return $this->json_extra['business_address'] ?? null;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 직급/직책 레이블
|
||||
// =========================================================================
|
||||
|
||||
public function getPositionLabelAttribute(): ?string
|
||||
{
|
||||
if (! $this->position_key || ! $this->tenant_id) {
|
||||
return $this->position_key;
|
||||
}
|
||||
|
||||
$position = Position::where('tenant_id', $this->tenant_id)
|
||||
->where('type', Position::TYPE_RANK)
|
||||
->where('key', $this->position_key)
|
||||
->first();
|
||||
|
||||
return $position?->name ?? $this->position_key;
|
||||
}
|
||||
|
||||
public function getJobTitleLabelAttribute(): ?string
|
||||
{
|
||||
if (! $this->job_title_key || ! $this->tenant_id) {
|
||||
return $this->job_title_key;
|
||||
}
|
||||
|
||||
$position = Position::where('tenant_id', $this->tenant_id)
|
||||
->where('type', Position::TYPE_TITLE)
|
||||
->where('key', $this->job_title_key)
|
||||
->first();
|
||||
|
||||
return $position?->name ?? $this->job_title_key;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// json_extra 헬퍼
|
||||
// =========================================================================
|
||||
|
||||
public function getJsonExtraValue(string $key, mixed $default = null): mixed
|
||||
{
|
||||
return $this->json_extra[$key] ?? $default;
|
||||
}
|
||||
|
||||
public function setJsonExtraValue(string $key, mixed $value): void
|
||||
{
|
||||
$extra = $this->json_extra ?? [];
|
||||
if ($value === null) {
|
||||
unset($extra[$key]);
|
||||
} else {
|
||||
$extra[$key] = $value;
|
||||
}
|
||||
$this->json_extra = $extra;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 스코프
|
||||
// =========================================================================
|
||||
|
||||
public function scopeForTenant($query, ?int $tenantId = null)
|
||||
{
|
||||
$tenantId = $tenantId ?? session('selected_tenant_id');
|
||||
if ($tenantId) {
|
||||
return $query->where('tenant_id', $tenantId);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function scopeActiveEmployees($query)
|
||||
{
|
||||
return $query->where('employee_status', 'active');
|
||||
}
|
||||
|
||||
public function scopeOnLeave($query)
|
||||
{
|
||||
return $query->where('employee_status', 'leave');
|
||||
}
|
||||
|
||||
public function scopeResigned($query)
|
||||
{
|
||||
return $query->where('employee_status', 'resigned');
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
use App\Models\Tenants\Department;
|
||||
use App\Models\User;
|
||||
use App\Traits\ModelTrait;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
@@ -23,12 +24,23 @@ class Employee extends Model
|
||||
'work_location_key',
|
||||
'employment_type_key',
|
||||
'employee_status',
|
||||
'worker_type',
|
||||
'manager_user_id',
|
||||
'json_extra',
|
||||
'profile_photo_path',
|
||||
'display_name',
|
||||
];
|
||||
|
||||
protected static function booted(): void
|
||||
{
|
||||
static::addGlobalScope('employee', function (Builder $builder) {
|
||||
$builder->where(function ($q) {
|
||||
$q->where('worker_type', 'employee')
|
||||
->orWhereNull('worker_type');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
protected $casts = [
|
||||
'json_extra' => 'array',
|
||||
'tenant_id' => 'int',
|
||||
|
||||
Reference in New Issue
Block a user