refactor: BOM API ref_id 통합 및 응답 개선
- child_product_id, material_id를 ref_id 단일 컬럼으로 통합 - splitRef() 메서드 제거 - bulkUpsert() 응답에 created_ids, updated_ids 추가
This commit is contained in:
@@ -36,9 +36,9 @@ public function index(int $parentProductId, array $params)
|
||||
->orderBy('sort_order')
|
||||
->get();
|
||||
|
||||
// 리졸브(제품/자재)
|
||||
$productIds = $items->where('ref_type', 'PRODUCT')->pluck('child_product_id')->filter()->unique()->values();
|
||||
$materialIds = $items->where('ref_type', 'MATERIAL')->pluck('material_id')->filter()->unique()->values();
|
||||
// 리졸브(제품/자재) - ref_id 기준
|
||||
$productIds = $items->where('ref_type', 'PRODUCT')->pluck('ref_id')->filter()->unique()->values();
|
||||
$materialIds = $items->where('ref_type', 'MATERIAL')->pluck('ref_id')->filter()->unique()->values();
|
||||
|
||||
$products = $productIds->isNotEmpty()
|
||||
? Product::query()->where('tenant_id', $tenantId)->whereIn('id', $productIds)->get(['id', 'code', 'name', 'product_type', 'category_id'])->keyBy('id')
|
||||
@@ -52,26 +52,25 @@ public function index(int $parentProductId, array $params)
|
||||
$base = [
|
||||
'id' => (int) $row->id,
|
||||
'ref_type' => $row->ref_type,
|
||||
'ref_id' => (int) $row->ref_id,
|
||||
'quantity' => $row->quantity,
|
||||
'sort_order' => (int) $row->sort_order,
|
||||
'is_default' => (int) $row->is_default,
|
||||
];
|
||||
|
||||
if ($row->ref_type === 'PRODUCT') {
|
||||
$p = $products->get($row->child_product_id);
|
||||
$p = $products->get($row->ref_id);
|
||||
|
||||
return $base + [
|
||||
'ref_id' => (int) $row->child_product_id,
|
||||
'code' => $p?->code,
|
||||
'name' => $p?->name,
|
||||
'product_type' => $p?->product_type,
|
||||
'category_id' => $p?->category_id,
|
||||
];
|
||||
} else { // MATERIAL
|
||||
$m = $materials->get($row->material_id);
|
||||
$m = $materials->get($row->ref_id);
|
||||
|
||||
return $base + [
|
||||
'ref_id' => (int) $row->material_id,
|
||||
'code' => $m?->code,
|
||||
'name' => $m?->name,
|
||||
'unit' => $m?->unit,
|
||||
@@ -98,8 +97,10 @@ public function bulkUpsert(int $parentProductId, array $items): array
|
||||
|
||||
$created = 0;
|
||||
$updated = 0;
|
||||
$createdIds = [];
|
||||
$updatedIds = [];
|
||||
|
||||
DB::transaction(function () use ($tenantId, $userId, $parentProductId, $items, &$created, &$updated) {
|
||||
DB::transaction(function () use ($tenantId, $userId, $parentProductId, $items, &$created, &$updated, &$createdIds, &$updatedIds) {
|
||||
foreach ($items as $it) {
|
||||
$payload = $this->validateItem($it);
|
||||
|
||||
@@ -115,40 +116,40 @@ public function bulkUpsert(int $parentProductId, array $items): array
|
||||
throw new BadRequestHttpException(__('error.not_found'));
|
||||
}
|
||||
|
||||
// ref 변경 허용 시: 충돌 검사
|
||||
[$childProductId, $materialId] = $this->splitRef($payload);
|
||||
|
||||
$pc->update([
|
||||
'ref_type' => $payload['ref_type'],
|
||||
'child_product_id' => $childProductId,
|
||||
'material_id' => $materialId,
|
||||
'ref_id' => (int) $payload['ref_id'],
|
||||
'quantity' => $payload['quantity'],
|
||||
'sort_order' => $payload['sort_order'] ?? $pc->sort_order,
|
||||
'is_default' => $payload['is_default'] ?? $pc->is_default,
|
||||
'updated_by' => $userId,
|
||||
]);
|
||||
$updated++;
|
||||
$updatedIds[] = $pc->id;
|
||||
} else {
|
||||
// 신규
|
||||
[$childProductId, $materialId] = $this->splitRef($payload);
|
||||
|
||||
ProductComponent::create([
|
||||
$pc = ProductComponent::create([
|
||||
'tenant_id' => $tenantId,
|
||||
'parent_product_id' => $parentProductId,
|
||||
'ref_type' => $payload['ref_type'],
|
||||
'child_product_id' => $childProductId,
|
||||
'material_id' => $materialId,
|
||||
'ref_id' => (int) $payload['ref_id'],
|
||||
'quantity' => $payload['quantity'],
|
||||
'sort_order' => $payload['sort_order'] ?? 0,
|
||||
'is_default' => $payload['is_default'] ?? 0,
|
||||
'created_by' => $userId,
|
||||
]);
|
||||
$created++;
|
||||
$createdIds[] = $pc->id;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return compact('created', 'updated');
|
||||
return [
|
||||
'created' => $created,
|
||||
'updated' => $updated,
|
||||
'created_ids' => $createdIds,
|
||||
'updated_ids' => $updatedIds,
|
||||
];
|
||||
}
|
||||
|
||||
// 단건 수정
|
||||
@@ -180,14 +181,12 @@ public function update(int $parentProductId, int $itemId, array $data)
|
||||
$refType = $payload['ref_type'] ?? $pc->ref_type;
|
||||
$refId = isset($payload['ref_id'])
|
||||
? (int) $payload['ref_id']
|
||||
: ($pc->ref_type === 'PRODUCT' ? (int) $pc->child_product_id : (int) $pc->material_id);
|
||||
: (int) $pc->ref_id;
|
||||
|
||||
$this->assertReference($tenantId, $parentProductId, $refType, $refId);
|
||||
[$childProductId, $materialId] = $this->splitRef(['ref_type' => $refType, 'ref_id' => $refId]);
|
||||
|
||||
$pc->ref_type = $refType;
|
||||
$pc->child_product_id = $childProductId;
|
||||
$pc->material_id = $materialId;
|
||||
$pc->ref_id = $refId;
|
||||
}
|
||||
|
||||
if (isset($payload['quantity'])) {
|
||||
@@ -290,14 +289,14 @@ public function validateBom(int $parentProductId): array
|
||||
if ($row->quantity <= 0) {
|
||||
$errors[] = ['id' => $row->id, 'error' => 'INVALID_QUANTITY'];
|
||||
}
|
||||
$key = $row->ref_type.':'.($row->ref_type === 'PRODUCT' ? $row->child_product_id : $row->material_id);
|
||||
$key = $row->ref_type.':'.$row->ref_id;
|
||||
if (isset($seen[$key])) {
|
||||
$errors[] = ['id' => $row->id, 'error' => 'DUPLICATE_ITEM'];
|
||||
} else {
|
||||
$seen[$key] = true;
|
||||
}
|
||||
// 자기참조
|
||||
if ($row->ref_type === 'PRODUCT' && (int) $row->child_product_id === (int) $parentProductId) {
|
||||
if ($row->ref_type === 'PRODUCT' && (int) $row->ref_id === (int) $parentProductId) {
|
||||
$errors[] = ['id' => $row->id, 'error' => 'SELF_REFERENCE'];
|
||||
}
|
||||
}
|
||||
@@ -324,16 +323,6 @@ private function validateItem(array $it): array
|
||||
return $v->validate();
|
||||
}
|
||||
|
||||
private function splitRef(array $payload): array
|
||||
{
|
||||
// returns [child_product_id, material_id]
|
||||
if ($payload['ref_type'] === 'PRODUCT') {
|
||||
return [(int) $payload['ref_id'], null];
|
||||
}
|
||||
|
||||
return [null, (int) $payload['ref_id']];
|
||||
}
|
||||
|
||||
private function assertProduct(int $tenantId, int $productId): void
|
||||
{
|
||||
$exists = Product::query()->where('tenant_id', $tenantId)->where('id', $productId)->exists();
|
||||
|
||||
Reference in New Issue
Block a user