refactor(work-orders): 코드 리뷰 기반 전면 개선
## Critical 수정 - Multi-tenancy: WorkOrderItem, BendingDetail, Issue에 BelongsToTenant 적용 - 감사 로그: 상태변경, 품목수정, 이슈 등록/해결 시 로깅 추가 - 상태 전이 규칙: STATUS_TRANSITIONS + canTransitionTo() 구현 ## High 수정 - 다중 담당자: work_order_assignees 피벗 테이블 및 관계 추가 - 부분 수정: 품목 ID 기반 upsert/delete 로직 구현 ## 변경 파일 - Models: WorkOrder, WorkOrderAssignee(신규), 하위 모델들 - Services: WorkOrderService (assign, update 메서드 개선) - Migrations: tenant_id 추가, assignees 테이블 생성 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -98,6 +98,19 @@ class WorkOrder extends Model
|
||||
self::STATUS_SHIPPED,
|
||||
];
|
||||
|
||||
/**
|
||||
* 상태 전이 규칙
|
||||
* [현재 상태 => [허용되는 다음 상태들]]
|
||||
*/
|
||||
public const STATUS_TRANSITIONS = [
|
||||
self::STATUS_UNASSIGNED => [self::STATUS_PENDING],
|
||||
self::STATUS_PENDING => [self::STATUS_UNASSIGNED, self::STATUS_WAITING],
|
||||
self::STATUS_WAITING => [self::STATUS_PENDING, self::STATUS_IN_PROGRESS],
|
||||
self::STATUS_IN_PROGRESS => [self::STATUS_WAITING, self::STATUS_COMPLETED],
|
||||
self::STATUS_COMPLETED => [self::STATUS_IN_PROGRESS, self::STATUS_SHIPPED],
|
||||
self::STATUS_SHIPPED => [self::STATUS_COMPLETED],
|
||||
];
|
||||
|
||||
// ──────────────────────────────────────────────────────────────
|
||||
// 관계
|
||||
// ──────────────────────────────────────────────────────────────
|
||||
@@ -111,13 +124,29 @@ public function salesOrder(): BelongsTo
|
||||
}
|
||||
|
||||
/**
|
||||
* 담당자
|
||||
* 담당자 (주 담당자 - 하위 호환)
|
||||
*/
|
||||
public function assignee(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'assignee_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* 담당자들 (다중 담당자)
|
||||
*/
|
||||
public function assignees(): HasMany
|
||||
{
|
||||
return $this->hasMany(WorkOrderAssignee::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 주 담당자 (다중 담당자 중)
|
||||
*/
|
||||
public function primaryAssignee(): HasMany
|
||||
{
|
||||
return $this->hasMany(WorkOrderAssignee::class)->where('is_primary', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 팀
|
||||
*/
|
||||
@@ -291,4 +320,41 @@ public function getOpenIssuesCountAttribute(): int
|
||||
{
|
||||
return $this->issues()->where('status', '!=', 'resolved')->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 상태로 전이 가능한지 확인
|
||||
*/
|
||||
public function canTransitionTo(string $newStatus): bool
|
||||
{
|
||||
$allowedTransitions = self::STATUS_TRANSITIONS[$this->status] ?? [];
|
||||
|
||||
return in_array($newStatus, $allowedTransitions);
|
||||
}
|
||||
|
||||
/**
|
||||
* 현재 상태에서 허용되는 다음 상태 목록 조회
|
||||
*/
|
||||
public function getAllowedTransitions(): array
|
||||
{
|
||||
return self::STATUS_TRANSITIONS[$this->status] ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 상태 전이 실행 (유효성 검증 포함)
|
||||
*
|
||||
* @throws \InvalidArgumentException 허용되지 않은 전이인 경우
|
||||
*/
|
||||
public function transitionTo(string $newStatus): bool
|
||||
{
|
||||
if (! $this->canTransitionTo($newStatus)) {
|
||||
$allowed = implode(', ', $this->getAllowedTransitions());
|
||||
throw new \InvalidArgumentException(
|
||||
"상태를 '{$this->status}'에서 '{$newStatus}'(으)로 변경할 수 없습니다. 허용된 상태: {$allowed}"
|
||||
);
|
||||
}
|
||||
|
||||
$this->status = $newStatus;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user