Files
sam-api/docs/specs/item-master-field-key-validation.md
hskwon d16f0410b8 feat: field_key 시스템 필드 예약어 검증 추가
- SystemFields 상수 클래스 생성 (app/Constants/)
  - source_table 기반 테이블별 예약어 관리
  - products/materials 테이블 고정 컬럼 정의
  - 공통 시스템 컬럼 포함
- ItemFieldService 수정
  - validateFieldKeyUnique에 시스템 필드 검증 추가
  - source_table 미지정시 그룹 전체 예약어 체크 (안전 모드)
- 에러 메시지 추가 (error.field_key_reserved)
- 작업 문서 추가 (docs/specs/item-master-field-key-validation.md)
2025-12-09 14:06:35 +09:00

5.6 KiB

Item Master field_key 검증 정책

개요

field_key 저장 및 검증 정책을 변경하여 시스템 필드(고정 컬럼)와의 충돌을 방지합니다.

변경 사항

1. field_key 저장 정책 변경

변경 전:

field_key = {id}_{입력값}
예: 98_code, 99_name

변경 후:

field_key = {입력값}
예: code, name (단, 시스템 예약어는 사용 불가)

2. 시스템 필드 예약어 검증 추가

검증 흐름

field_key 입력
    ↓
source_table 확인 (products / materials)
    ↓
해당 테이블 예약어 체크
    ↓
기존 필드 중복 체크
    ↓
저장

source_table 기반 예약어 매핑

source_table 대상 테이블 예약어 목록
products products code, name, unit, product_type, ...
materials materials name, material_code, material_type, ...
null 전체 products + materials 예약어 모두 체크 (안전 모드)

구현 상세

파일 구조

app/
├── Constants/
│   └── SystemFields.php          # 신규: 예약어 상수 클래스
└── Services/
    └── ItemMaster/
        └── ItemFieldService.php  # 수정: 예약어 검증 추가

SystemFields 상수 클래스

// app/Constants/SystemFields.php

class SystemFields
{
    // 소스 테이블 상수
    public const SOURCE_TABLE_PRODUCTS = 'products';
    public const SOURCE_TABLE_MATERIALS = 'materials';

    // 그룹 ID 상수
    public const GROUP_ITEM_MASTER = 1;

    // products 테이블 고정 컬럼
    public const PRODUCTS = [
        'code', 'name', 'unit', 'category_id', 'product_type', 'description',
        'is_sellable', 'is_purchasable', 'is_producible', 'is_variable_size', 'is_active',
        'safety_stock', 'lead_time', 'product_category', 'part_type',
        'bending_diagram', 'bending_details',
        'specification_file', 'specification_file_name',
        'certification_file', 'certification_file_name',
        'certification_number', 'certification_start_date', 'certification_end_date',
        'attributes', 'attributes_archive',
    ];

    // materials 테이블 고정 컬럼
    public const MATERIALS = [
        'name', 'item_name', 'specification', 'material_code', 'material_type',
        'unit', 'category_id', 'is_inspection', 'is_active',
        'search_tag', 'remarks', 'attributes', 'options',
    ];

    // 공통 시스템 컬럼
    public const COMMON = [
        'id', 'tenant_id', 'created_by', 'updated_by', 'deleted_by',
        'created_at', 'updated_at', 'deleted_at',
    ];

    // source_table 기반 예약어 조회
    public static function getReservedKeys(string $sourceTable): array;

    // 예약어 여부 확인
    public static function isReserved(string $fieldKey, string $sourceTable): bool;

    // 그룹 내 전체 예약어 조회 (안전 모드)
    public static function getAllReservedKeysForGroup(int $groupId): array;

    // 그룹 내 예약어 여부 확인
    public static function isReservedInGroup(string $fieldKey, int $groupId): bool;
}

ItemFieldService 검증 메서드

private function validateFieldKeyUnique(
    string $fieldKey,
    int $tenantId,
    ?string $sourceTable = null,
    int $groupId = 1,
    ?int $excludeId = null
): void {
    // 1. 시스템 필드(예약어) 체크
    if ($sourceTable) {
        if (SystemFields::isReserved($fieldKey, $sourceTable)) {
            throw ValidationException::withMessages([
                'field_key' => [__('error.field_key_reserved', ['field_key' => $fieldKey])],
            ]);
        }
    } else {
        // 안전 모드: 그룹 내 모든 테이블 예약어 체크
        if (SystemFields::isReservedInGroup($fieldKey, $groupId)) {
            throw ValidationException::withMessages([
                'field_key' => [__('error.field_key_reserved', ['field_key' => $fieldKey])],
            ]);
        }
    }

    // 2. 기존 필드 중복 체크
    // ...
}

호출 예시

// 독립 필드 생성 시
$this->validateFieldKeyUnique(
    $data['field_key'],
    $tenantId,
    $data['source_table'] ?? null,  // 'products' 또는 'materials'
    $data['group_id'] ?? 1
);

// 필드 수정 시
$this->validateFieldKeyUnique(
    $data['field_key'],
    $tenantId,
    $data['source_table'] ?? null,
    $field->group_id ?? 1,
    $id  // excludeId
);

에러 메시지

상황 메시지 키 메시지
시스템 예약어 충돌 error.field_key_reserved "code"은(는) 시스템 예약어로 사용할 수 없습니다.
기존 필드 중복 validation.unique field_key은(는) 이미 사용 중입니다.
// lang/ko/error.php
'field_key_reserved' => '":field_key"은(는) 시스템 예약어로 사용할 수 없습니다.',

// lang/ko/validation.php (Laravel 기본)
'unique' => ':attribute은(는) 이미 사용 중입니다.',

clone 메서드 field_key 복제 정책

원본 field_key: custom_field
복제본: custom_field_copy

중복 시: custom_field_copy2, custom_field_copy3, ...

관련 파일

파일 변경 유형 설명
app/Constants/SystemFields.php 신규 예약어 상수 클래스
app/Services/ItemMaster/ItemFieldService.php 수정 검증 로직 추가
lang/ko/error.php 수정 에러 메시지 추가

참고

  • ItemPage 테이블의 source_table 컬럼: 실제 저장 테이블명 (products, materials)
  • ItemPage 테이블의 item_type 컬럼: FG, PT, SM, RM, CS (품목 유형 코드)
  • group_id: 카테고리 격리용 (1 = 품목관리)