refactor: [절곡] code/lot_no 분리 — 코드 체계와 LOT 번호 분리
- bending_items.code: LOT번호(CP260319) → 코드체계(CP)만 저장 - bending_items.lot_no: 기존 code 값 이관 (LOT 번호) - bending_models.code: 전체코드(GR-KSS01-벽면형-SUS) → 접두사(GR)만 저장 - bending_models.lot_no: 기존 code 값 이관 - unique 제약: code → lot_no로 이동 - BendingCodeService.resolveItem: LIKE → 정확 매칭 - 검색: lot_no 필드 추가 - Swagger 문서 업데이트
This commit is contained in:
@@ -14,9 +14,10 @@ public function authorize(): bool
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'code' => [
|
||||
'required', 'string', 'max:50',
|
||||
\Illuminate\Validation\Rule::unique('bending_items', 'code')->where('tenant_id', request()->header('X-TENANT-ID', app()->bound('tenant_id') ? app('tenant_id') : 1)),
|
||||
'code' => 'required|string|max:10',
|
||||
'lot_no' => [
|
||||
'nullable', 'string', 'max:50',
|
||||
\Illuminate\Validation\Rule::unique('bending_items', 'lot_no')->where('tenant_id', request()->header('X-TENANT-ID', app()->bound('tenant_id') ? app('tenant_id') : 1)),
|
||||
],
|
||||
'item_name' => 'required|string|max:50',
|
||||
'item_sep' => 'required|in:스크린,철재',
|
||||
|
||||
@@ -14,7 +14,8 @@ public function authorize(): bool
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'code' => 'sometimes|string|max:100',
|
||||
'code' => 'sometimes|string|max:10',
|
||||
'lot_no' => 'nullable|string|max:50',
|
||||
'name' => 'sometimes|string|max:200',
|
||||
'item_name' => 'sometimes|string|max:50',
|
||||
'item_sep' => 'sometimes|in:스크린,철재',
|
||||
|
||||
@@ -12,6 +12,7 @@ public function toArray(Request $request): array
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'code' => $this->code,
|
||||
'lot_no' => $this->lot_no,
|
||||
'legacy_code' => $this->legacy_code,
|
||||
// 정규 컬럼 직접 참조
|
||||
'item_name' => $this->item_name,
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
/**
|
||||
* 절곡 기초관리 마스터
|
||||
*
|
||||
* code: {제품Code}{종류Code}{YYMMDD} (예: CP260319 = 케이스 점검구)
|
||||
* code: 코드 체계 (제품Code+종류Code, 예: CP = 케이스 점검구)
|
||||
* lot_no: LOT 번호 (code+날짜+일련, 예: CP260319-02)
|
||||
* bending_data: 전개도 JSON 배열 [{no, input, rate, sum, color, aAngle}]
|
||||
*/
|
||||
class BendingItem extends Model
|
||||
@@ -24,6 +25,7 @@ class BendingItem extends Model
|
||||
protected $fillable = [
|
||||
'tenant_id',
|
||||
'code',
|
||||
'lot_no',
|
||||
'legacy_code',
|
||||
'legacy_bending_id',
|
||||
'item_name',
|
||||
|
||||
@@ -134,9 +134,9 @@ public function getCodeMap(): array
|
||||
*/
|
||||
public function resolveItem(string $prodCode, string $specCode, string $lengthCode): ?array
|
||||
{
|
||||
// 1차: code + length_code로 조회 (신규 LOT 체계)
|
||||
// 1차: code(코드 체계) + length_code로 조회
|
||||
$item = BendingItem::where('tenant_id', $this->tenantId())
|
||||
->where('code', 'like', "{$prodCode}{$specCode}%")
|
||||
->where('code', "{$prodCode}{$specCode}")
|
||||
->where('length_code', $lengthCode)
|
||||
->where('is_active', true)
|
||||
->first();
|
||||
@@ -156,7 +156,7 @@ public function resolveItem(string $prodCode, string $specCode, string $lengthCo
|
||||
|
||||
return [
|
||||
'item_id' => $item->id,
|
||||
'item_code' => $item->code,
|
||||
'item_code' => $item->lot_no ?? $item->code,
|
||||
'item_name' => $item->item_name,
|
||||
'specification' => $item->item_spec,
|
||||
'unit' => 'EA',
|
||||
|
||||
@@ -20,6 +20,7 @@ public function list(array $params): LengthAwarePaginator
|
||||
fn ($q2) => $q2
|
||||
->where('item_name', 'like', "%{$v}%")
|
||||
->orWhere('code', 'like', "%{$v}%")
|
||||
->orWhere('lot_no', 'like', "%{$v}%")
|
||||
->orWhere('item_spec', 'like', "%{$v}%")
|
||||
->orWhere('legacy_code', 'like', "%{$v}%")
|
||||
))
|
||||
@@ -48,6 +49,7 @@ public function create(array $data): BendingItem
|
||||
return BendingItem::create([
|
||||
'tenant_id' => $this->tenantId(),
|
||||
'code' => $data['code'],
|
||||
'lot_no' => $data['lot_no'] ?? null,
|
||||
'legacy_code' => $data['legacy_code'] ?? null,
|
||||
'legacy_bending_id' => $data['legacy_bending_id'] ?? null,
|
||||
'item_name' => $data['item_name'] ?? $data['name'] ?? '',
|
||||
@@ -77,7 +79,7 @@ public function update(int $id, array $data): BendingItem
|
||||
$item = BendingItem::findOrFail($id);
|
||||
|
||||
$columns = [
|
||||
'code', 'item_name', 'item_sep', 'item_bending',
|
||||
'code', 'lot_no', 'item_name', 'item_sep', 'item_bending',
|
||||
'material', 'item_spec', 'model_name', 'model_UA',
|
||||
'rail_width', 'exit_direction', 'box_width', 'box_height',
|
||||
'front_bottom', 'inspection_door', 'length_code', 'length_mm',
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
* @OA\Schema(
|
||||
* schema="BendingItem",
|
||||
* @OA\Property(property="id", type="integer", example=431),
|
||||
* @OA\Property(property="code", type="string", example="RS260319", description="LOT 코드: {제품Code}{종류Code}{YYMMDD}"),
|
||||
* @OA\Property(property="code", type="string", example="RS", description="코드 체계 (제품Code+종류Code)"),
|
||||
* @OA\Property(property="lot_no", type="string", nullable=true, example="RS260319", description="LOT 번호 (code+날짜+일련번호)"),
|
||||
* @OA\Property(property="legacy_code", type="string", nullable=true, example="BD-RS-30", description="이전 코드 (items 기반)"),
|
||||
* @OA\Property(property="item_name", type="string", example="SUS마감재"),
|
||||
* @OA\Property(property="item_sep", type="string", enum={"스크린","철재"}),
|
||||
@@ -120,7 +121,8 @@ public function show() {}
|
||||
* summary="절곡품 등록",
|
||||
* @OA\RequestBody(@OA\JsonContent(
|
||||
* required={"code","item_name","item_sep","item_bending","material"},
|
||||
* @OA\Property(property="code", type="string", example="RM260319", description="LOT 코드"),
|
||||
* @OA\Property(property="code", type="string", example="RM", description="코드 체계 (prod+spec)"),
|
||||
* @OA\Property(property="lot_no", type="string", nullable=true, example="RM260319", description="LOT 번호"),
|
||||
* @OA\Property(property="item_name", type="string", example="본체"),
|
||||
* @OA\Property(property="item_sep", type="string", enum={"스크린","철재"}),
|
||||
* @OA\Property(property="item_bending", type="string", example="가이드레일"),
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
// ── bending_items ──
|
||||
Schema::table('bending_items', function (Blueprint $table) {
|
||||
$table->string('lot_no', 50)->nullable()->after('code')->comment('LOT 번호 (기존 code 값 이관)');
|
||||
});
|
||||
|
||||
// 기존 code → lot_no 이관, code에는 앞 2자리(prod+spec)만 남기기
|
||||
DB::statement("UPDATE bending_items SET lot_no = code, code = LEFT(code, 2) WHERE lot_no IS NULL");
|
||||
|
||||
// unique 제약 변경: code → lot_no
|
||||
Schema::table('bending_items', function (Blueprint $table) {
|
||||
// 기존 unique 제거
|
||||
$indexes = collect(DB::select("SHOW INDEX FROM bending_items WHERE Key_name = 'uk_tenant_code'"));
|
||||
if ($indexes->isNotEmpty()) {
|
||||
$table->dropUnique('uk_tenant_code');
|
||||
}
|
||||
// lot_no에 unique 추가
|
||||
$table->unique(['tenant_id', 'lot_no', 'deleted_at'], 'uk_tenant_lot_no');
|
||||
// code 인덱스 유지 (필터용)
|
||||
$table->index('code', 'idx_bending_code_type');
|
||||
});
|
||||
|
||||
// ── bending_models ──
|
||||
Schema::table('bending_models', function (Blueprint $table) {
|
||||
$table->string('lot_no', 100)->nullable()->after('code')->comment('전체 코드 (기존 code 값 이관)');
|
||||
});
|
||||
|
||||
// 기존 code → lot_no 이관, code에는 접두사만 남기기 (GR-, SB-, BB-)
|
||||
DB::statement("UPDATE bending_models SET lot_no = code, code = CASE
|
||||
WHEN code LIKE 'GR-%' THEN 'GR'
|
||||
WHEN code LIKE 'SB-%' THEN 'SB'
|
||||
WHEN code LIKE 'BB-%' THEN 'BB'
|
||||
ELSE LEFT(code, 2)
|
||||
END WHERE lot_no IS NULL");
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
// bending_items: lot_no → code 복원
|
||||
DB::statement("UPDATE bending_items SET code = lot_no WHERE lot_no IS NOT NULL");
|
||||
Schema::table('bending_items', function (Blueprint $table) {
|
||||
$indexes = collect(DB::select("SHOW INDEX FROM bending_items WHERE Key_name = 'uk_tenant_lot_no'"));
|
||||
if ($indexes->isNotEmpty()) {
|
||||
$table->dropUnique('uk_tenant_lot_no');
|
||||
}
|
||||
$indexes2 = collect(DB::select("SHOW INDEX FROM bending_items WHERE Key_name = 'idx_bending_code_type'"));
|
||||
if ($indexes2->isNotEmpty()) {
|
||||
$table->dropIndex('idx_bending_code_type');
|
||||
}
|
||||
$table->unique(['tenant_id', 'code', 'deleted_at'], 'uk_tenant_code');
|
||||
$table->dropColumn('lot_no');
|
||||
});
|
||||
|
||||
// bending_models: lot_no → code 복원
|
||||
DB::statement("UPDATE bending_models SET code = lot_no WHERE lot_no IS NOT NULL");
|
||||
Schema::table('bending_models', function (Blueprint $table) {
|
||||
$table->dropColumn('lot_no');
|
||||
});
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user