feat(item-master): 잠금 기능 추가 및 FK 레거시 코드 정리
## 잠금 기능 (Lock Feature) - entity_relationships 테이블에 is_locked, locked_by, locked_at 컬럼 추가 - EntityRelationship 모델에 잠금 관련 헬퍼 메서드 추가 - LockCheckTrait 생성 (destroy 시 잠금 체크 공통 로직) - 각 Service의 destroy() 메서드에 잠금 체크 적용 - API 응답에 is_locked 필드 포함 - 한국어 에러 메시지 추가 ## FK 레거시 코드 정리 - ItemMasterSeeder: entity_relationships 기반으로 전환 - ItemPage 모델: FK 기반 sections() 관계 제거 - ItemSectionService: clone() 메서드 FK 제거 - SectionTemplateService: page_id 컬럼 참조 제거 - EntityRelationship::link() 파라미터 순서 통일 ## 기타 - Swagger 스키마에 is_locked 속성 추가 - 프론트엔드 가이드 문서 추가
This commit is contained in:
@@ -7,11 +7,14 @@
|
||||
use App\Models\ItemMaster\ItemField;
|
||||
use App\Models\ItemMaster\ItemSection;
|
||||
use App\Services\Service;
|
||||
use App\Traits\LockCheckTrait;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
class ItemSectionService extends Service
|
||||
{
|
||||
use LockCheckTrait;
|
||||
|
||||
/**
|
||||
* 모든 섹션 목록 조회
|
||||
*
|
||||
@@ -89,12 +92,11 @@ public function clone(int $id): ItemSection
|
||||
'created_by' => $userId,
|
||||
]);
|
||||
|
||||
// 필드 복제
|
||||
foreach ($original->fields as $field) {
|
||||
ItemField::create([
|
||||
// 필드 복제 (entity_relationships 기반)
|
||||
foreach ($original->fields as $orderNo => $field) {
|
||||
$clonedField = ItemField::create([
|
||||
'tenant_id' => $tenantId,
|
||||
'group_id' => $field->group_id,
|
||||
'section_id' => $cloned->id,
|
||||
'field_name' => $field->field_name,
|
||||
'field_type' => $field->field_type,
|
||||
'order_no' => $field->order_no,
|
||||
@@ -107,14 +109,25 @@ public function clone(int $id): ItemSection
|
||||
'properties' => $field->properties,
|
||||
'created_by' => $userId,
|
||||
]);
|
||||
|
||||
// 섹션-필드 관계 생성
|
||||
EntityRelationship::link(
|
||||
$tenantId,
|
||||
EntityRelationship::TYPE_SECTION,
|
||||
$cloned->id,
|
||||
EntityRelationship::TYPE_FIELD,
|
||||
$clonedField->id,
|
||||
$field->order_no,
|
||||
null,
|
||||
$field->group_id
|
||||
);
|
||||
}
|
||||
|
||||
// BOM 항목 복제
|
||||
foreach ($original->bomItems as $bom) {
|
||||
ItemBomItem::create([
|
||||
// BOM 항목 복제 (entity_relationships 기반)
|
||||
foreach ($original->bomItems as $orderNo => $bom) {
|
||||
$clonedBom = ItemBomItem::create([
|
||||
'tenant_id' => $tenantId,
|
||||
'group_id' => $bom->group_id,
|
||||
'section_id' => $cloned->id,
|
||||
'item_code' => $bom->item_code,
|
||||
'item_name' => $bom->item_name,
|
||||
'quantity' => $bom->quantity,
|
||||
@@ -125,6 +138,18 @@ public function clone(int $id): ItemSection
|
||||
'note' => $bom->note,
|
||||
'created_by' => $userId,
|
||||
]);
|
||||
|
||||
// 섹션-BOM 관계 생성
|
||||
EntityRelationship::link(
|
||||
$tenantId,
|
||||
EntityRelationship::TYPE_SECTION,
|
||||
$cloned->id,
|
||||
EntityRelationship::TYPE_BOM,
|
||||
$clonedBom->id,
|
||||
$orderNo,
|
||||
null,
|
||||
$bom->group_id
|
||||
);
|
||||
}
|
||||
|
||||
return $cloned->load(['fields', 'bomItems']);
|
||||
@@ -227,6 +252,8 @@ public function update(int $id, array $data): ItemSection
|
||||
* 섹션 삭제 (Soft Delete)
|
||||
*
|
||||
* 독립 엔티티 아키텍처: 섹션만 삭제하고 연결된 필드/BOM은 unlink만 수행
|
||||
*
|
||||
* @throws \App\Exceptions\BusinessException 잠금된 연결이 있는 경우
|
||||
*/
|
||||
public function destroy(int $id): void
|
||||
{
|
||||
@@ -241,17 +268,25 @@ public function destroy(int $id): void
|
||||
throw new NotFoundHttpException(__('error.not_found'));
|
||||
}
|
||||
|
||||
// 잠금 체크: 이 섹션이 잠금된 연결로 보호되고 있는지 확인
|
||||
$this->checkCanDelete(EntityRelationship::TYPE_SECTION, $id);
|
||||
|
||||
// 1. entity_relationships에서 이 섹션의 모든 부모 관계 해제
|
||||
// (page→section 관계에서 이 섹션 제거)
|
||||
// 주의: 잠금된 연결이 있으면 예외 발생
|
||||
EntityRelationship::where('child_type', EntityRelationship::TYPE_SECTION)
|
||||
->where('child_id', $id)
|
||||
->where('is_locked', false)
|
||||
->delete();
|
||||
|
||||
// 2. entity_relationships에서 이 섹션의 모든 자식 관계 해제
|
||||
// (section→field, section→bom 관계 삭제)
|
||||
EntityRelationship::where('parent_type', EntityRelationship::TYPE_SECTION)
|
||||
->where('parent_id', $id)
|
||||
->delete();
|
||||
// 주의: 잠금된 연결이 있으면 예외 발생 (unlinkAllChildren에서 처리)
|
||||
EntityRelationship::unlinkAllChildren(
|
||||
$tenantId,
|
||||
EntityRelationship::TYPE_SECTION,
|
||||
$id
|
||||
);
|
||||
|
||||
// 3. 섹션만 Soft Delete (필드/BOM은 독립 엔티티로 유지)
|
||||
$section->update(['deleted_by' => $userId]);
|
||||
|
||||
Reference in New Issue
Block a user