Files
sam-api/app/Models/Tenants/Salary.php
kent 0fef26f42a feat: HR 모델 userProfile 관계 추가 및 서비스 개선
## 모델 개선
- Leave: userProfile relation 추가
- Salary: userProfile relation 추가
- TenantUserProfile: department, position 관계 및 label accessor 추가

## 서비스 개선
- LeaveService: userProfile eager loading 추가
- SalaryService: 사원 정보 조회 개선
- CardService: 관계 정리 및 개선
- AttendanceService: 조회 기능 개선

## 시더
- DummySalarySeeder 추가
- DummyCardSeeder 멀티테넌트 지원 개선
- DummyDataSeeder에 급여 시더 등록

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 01:32:07 +09:00

176 lines
4.1 KiB
PHP

<?php
namespace App\Models\Tenants;
use App\Models\Members\User;
use App\Traits\BelongsToTenant;
use App\Traits\ModelTrait;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\SoftDeletes;
/**
* 급여 모델
*
* @property int $id
* @property int $tenant_id
* @property int $employee_id
* @property int $year
* @property int $month
* @property float $base_salary
* @property float $total_allowance
* @property float $total_overtime
* @property float $total_bonus
* @property float $total_deduction
* @property float $net_payment
* @property array|null $allowance_details
* @property array|null $deduction_details
* @property string|null $payment_date
* @property string $status
* @property int|null $created_by
* @property int|null $updated_by
* @property int|null $deleted_by
*/
class Salary extends Model
{
use BelongsToTenant, ModelTrait, SoftDeletes;
protected $table = 'salaries';
protected $fillable = [
'tenant_id',
'employee_id',
'year',
'month',
'base_salary',
'total_allowance',
'total_overtime',
'total_bonus',
'total_deduction',
'net_payment',
'allowance_details',
'deduction_details',
'payment_date',
'status',
'created_by',
'updated_by',
'deleted_by',
];
protected $casts = [
'base_salary' => 'decimal:2',
'total_allowance' => 'decimal:2',
'total_overtime' => 'decimal:2',
'total_bonus' => 'decimal:2',
'total_deduction' => 'decimal:2',
'net_payment' => 'decimal:2',
'allowance_details' => 'array',
'deduction_details' => 'array',
'payment_date' => 'date',
];
protected $attributes = [
'status' => 'scheduled',
'base_salary' => 0,
'total_allowance' => 0,
'total_overtime' => 0,
'total_bonus' => 0,
'total_deduction' => 0,
'net_payment' => 0,
];
// =========================================================================
// 관계 정의
// =========================================================================
/**
* 직원
*/
public function employee(): BelongsTo
{
return $this->belongsTo(User::class, 'employee_id');
}
/**
* 생성자
*/
public function creator(): BelongsTo
{
return $this->belongsTo(User::class, 'created_by');
}
/**
* 수정자
*/
public function updater(): BelongsTo
{
return $this->belongsTo(User::class, 'updated_by');
}
/**
* 직원 프로필 (테넌트별)
* 주의: eager loading 시 constrain 필요
* ->with(['employeeProfile' => fn($q) => $q->where('tenant_id', $tenantId)])
*/
public function employeeProfile(): HasOne
{
return $this->hasOne(TenantUserProfile::class, 'user_id', 'employee_id');
}
// =========================================================================
// 헬퍼 메서드
// =========================================================================
/**
* 지급 완료 여부
*/
public function isCompleted(): bool
{
return $this->status === 'completed';
}
/**
* 지급 예정 여부
*/
public function isScheduled(): bool
{
return $this->status === 'scheduled';
}
/**
* 상태 변경
*/
public function markAsCompleted(): void
{
$this->status = 'completed';
}
/**
* 상태 변경
*/
public function markAsScheduled(): void
{
$this->status = 'scheduled';
}
/**
* 실지급액 계산
*/
public function calculateNetPayment(): float
{
return $this->base_salary
+ $this->total_allowance
+ $this->total_overtime
+ $this->total_bonus
- $this->total_deduction;
}
/**
* 년월 표시
*/
public function getPeriodLabel(): string
{
return sprintf('%d년 %d월', $this->year, $this->month);
}
}