fix: [items] 품목 규격 accessor + 감사로그 + bom_category 마이그레이션
- Item 모델에 specification accessor 추가 (attributes.spec 조회) - ItemService.update()에 AuditLogger 감사 로그 추가 - items.options에 bom_category 추가 마이그레이션
This commit is contained in:
@@ -28,6 +28,7 @@ public function index(Request $request)
|
||||
'category_id' => $request->input('category_id'),
|
||||
'item_type' => $request->input('type') ?? $request->input('item_type'),
|
||||
'item_category' => $request->input('item_category'),
|
||||
'bom_category' => $request->input('bom_category'),
|
||||
'group_id' => $request->input('group_id'),
|
||||
'active' => $request->input('is_active') ?? $request->input('active'),
|
||||
'has_bom' => $request->input('has_bom'),
|
||||
|
||||
@@ -51,6 +51,24 @@ class Item extends Model
|
||||
'deleted_at',
|
||||
];
|
||||
|
||||
protected $appends = [
|
||||
'specification',
|
||||
];
|
||||
|
||||
/**
|
||||
* 규격 accessor — attributes JSON 내 spec/specification 값을 최상위 필드로 노출
|
||||
*/
|
||||
public function getSpecificationAttribute(): ?string
|
||||
{
|
||||
$attrs = $this->getAttributeValue('attributes');
|
||||
|
||||
if (is_array($attrs)) {
|
||||
return $attrs['spec'] ?? $attrs['specification'] ?? null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* item_type 상수
|
||||
*/
|
||||
|
||||
@@ -357,6 +357,7 @@ public function index(array $params): LengthAwarePaginator
|
||||
$categoryId = $params['category_id'] ?? null;
|
||||
$itemType = $params['item_type'] ?? null;
|
||||
$itemCategory = $params['item_category'] ?? null;
|
||||
$bomCategory = $params['bom_category'] ?? null;
|
||||
$groupId = $params['group_id'] ?? null;
|
||||
$active = $params['active'] ?? null;
|
||||
$hasBom = $params['has_bom'] ?? null;
|
||||
@@ -410,6 +411,11 @@ public function index(array $params): LengthAwarePaginator
|
||||
$query->where('item_category', $itemCategory);
|
||||
}
|
||||
|
||||
// BOM 카테고리 (options->bom_category)
|
||||
if ($bomCategory) {
|
||||
$query->where('options->bom_category', $bomCategory);
|
||||
}
|
||||
|
||||
// 활성 상태
|
||||
if ($active !== null && $active !== '') {
|
||||
$query->where('is_active', (bool) $active);
|
||||
@@ -743,6 +749,9 @@ public function update(int $id, array $data): Model
|
||||
$data['attributes'] = array_merge($existingAttributes, $data['attributes']);
|
||||
}
|
||||
|
||||
// 변경 전 스냅샷 (감사 로그용)
|
||||
$before = $item->toArray();
|
||||
|
||||
// 테이블 업데이트
|
||||
$itemData = array_intersect_key($data, array_flip([
|
||||
'item_type', 'code', 'name', 'unit', 'category_id',
|
||||
@@ -768,7 +777,19 @@ public function update(int $id, array $data): Model
|
||||
$item->load('details');
|
||||
}
|
||||
|
||||
return $item->refresh();
|
||||
$item->refresh();
|
||||
|
||||
// 감사 로그
|
||||
app(\App\Services\Audit\AuditLogger::class)->log(
|
||||
tenantId: $tenantId,
|
||||
targetType: 'item',
|
||||
targetId: $item->id,
|
||||
action: 'updated',
|
||||
before: $before,
|
||||
after: $item->toArray()
|
||||
);
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
/**
|
||||
* 품목 options JSON에 bom_category 필드 일괄 추가
|
||||
*
|
||||
* BOM 카테고리: material, motor, controller, steel, parts, inspection
|
||||
* 매핑 규칙:
|
||||
* - EST-RAW-* → material (주자재)
|
||||
* - RM (원자재) → material
|
||||
* - EST-MOTOR-* → motor (모터)
|
||||
* - EST-CTRL-* → controller (제어기)
|
||||
* - BD-* (BENDING) → steel (절곡품)
|
||||
* - EST-INSPECTION → inspection (검사비)
|
||||
* - CS (소모품) → inspection
|
||||
* - 나머지 PT/SM → parts (부자재)
|
||||
*/
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
// 1. material: EST-RAW-* 코드
|
||||
DB::table('items')
|
||||
->where('code', 'like', 'EST-RAW-%')
|
||||
->update([
|
||||
'options' => DB::raw("JSON_SET(COALESCE(options, '{}'), '$.bom_category', 'material')"),
|
||||
]);
|
||||
|
||||
// 2. material: RM (원자재) 타입
|
||||
DB::table('items')
|
||||
->where('item_type', 'RM')
|
||||
->update([
|
||||
'options' => DB::raw("JSON_SET(COALESCE(options, '{}'), '$.bom_category', 'material')"),
|
||||
]);
|
||||
|
||||
// 3. motor: EST-MOTOR-* 코드
|
||||
DB::table('items')
|
||||
->where('code', 'like', 'EST-MOTOR-%')
|
||||
->update([
|
||||
'options' => DB::raw("JSON_SET(COALESCE(options, '{}'), '$.bom_category', 'motor')"),
|
||||
]);
|
||||
|
||||
// 4. controller: EST-CTRL-* 코드
|
||||
DB::table('items')
|
||||
->where('code', 'like', 'EST-CTRL-%')
|
||||
->update([
|
||||
'options' => DB::raw("JSON_SET(COALESCE(options, '{}'), '$.bom_category', 'controller')"),
|
||||
]);
|
||||
|
||||
// 5. steel: item_category=BENDING (BD-* 코드)
|
||||
DB::table('items')
|
||||
->where('item_category', 'BENDING')
|
||||
->update([
|
||||
'options' => DB::raw("JSON_SET(COALESCE(options, '{}'), '$.bom_category', 'steel')"),
|
||||
]);
|
||||
|
||||
// 6. inspection: EST-INSPECTION 코드
|
||||
DB::table('items')
|
||||
->where('code', 'EST-INSPECTION')
|
||||
->update([
|
||||
'options' => DB::raw("JSON_SET(COALESCE(options, '{}'), '$.bom_category', 'inspection')"),
|
||||
]);
|
||||
|
||||
// 7. inspection: CS (소모품) 타입
|
||||
DB::table('items')
|
||||
->where('item_type', 'CS')
|
||||
->update([
|
||||
'options' => DB::raw("JSON_SET(COALESCE(options, '{}'), '$.bom_category', 'inspection')"),
|
||||
]);
|
||||
|
||||
// 8. parts: 나머지 PT/SM (아직 bom_category가 없는 것)
|
||||
DB::table('items')
|
||||
->whereIn('item_type', ['PT', 'SM'])
|
||||
->whereRaw("(options IS NULL OR JSON_EXTRACT(options, '$.bom_category') IS NULL)")
|
||||
->update([
|
||||
'options' => DB::raw("JSON_SET(COALESCE(options, '{}'), '$.bom_category', 'parts')"),
|
||||
]);
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
DB::table('items')
|
||||
->whereRaw("JSON_EXTRACT(options, '$.bom_category') IS NOT NULL")
|
||||
->update([
|
||||
'options' => DB::raw("JSON_REMOVE(options, '$.bom_category')"),
|
||||
]);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user