feat: Items API CRUD 기능 추가 (BP-MES Phase 1 Day 3-5)
- ItemsController 및 ItemsService CRUD 메서드 구현 - FormRequest 검증 클래스 추가 (ItemStoreRequest, ItemUpdateRequest) - Swagger 문서 완성 (ItemsApi.php) - 품목 생성/조회/수정/삭제 엔드포인트 추가 - i18n 메시지 키 추가 (message.item) - Code 기반 라우팅 적용 - Hybrid 구조 지원 (고정 필드 + attributes JSON)
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
use App\Models\Materials\Material;
|
||||
use App\Models\Products\Product;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
class ItemsService extends Service
|
||||
@@ -220,4 +221,122 @@ private function fetchPrices(string $itemType, int $itemId, ?int $clientId, ?str
|
||||
'purchase' => $purchasePrice,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 품목 생성 (Product 전용)
|
||||
*
|
||||
* @param array $data 검증된 데이터
|
||||
*/
|
||||
public function createItem(array $data): Product
|
||||
{
|
||||
$tenantId = $this->tenantId();
|
||||
$userId = $this->apiUserId();
|
||||
|
||||
// 품목 코드 중복 체크
|
||||
$exists = Product::query()
|
||||
->where('tenant_id', $tenantId)
|
||||
->where('code', $data['code'])
|
||||
->exists();
|
||||
|
||||
if ($exists) {
|
||||
throw new BadRequestHttpException(__('error.duplicate_code'));
|
||||
}
|
||||
|
||||
$payload = $data;
|
||||
$payload['tenant_id'] = $tenantId;
|
||||
$payload['created_by'] = $userId;
|
||||
$payload['is_sellable'] = $payload['is_sellable'] ?? true;
|
||||
$payload['is_purchasable'] = $payload['is_purchasable'] ?? false;
|
||||
$payload['is_producible'] = $payload['is_producible'] ?? false;
|
||||
|
||||
return Product::create($payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* 품목 수정 (Product 전용)
|
||||
*
|
||||
* @param string $code 품목 코드
|
||||
* @param array $data 검증된 데이터
|
||||
*/
|
||||
public function updateItem(string $code, array $data): Product
|
||||
{
|
||||
$tenantId = $this->tenantId();
|
||||
$userId = $this->apiUserId();
|
||||
|
||||
$product = Product::query()
|
||||
->where('tenant_id', $tenantId)
|
||||
->where('code', $code)
|
||||
->first();
|
||||
|
||||
if (! $product) {
|
||||
throw new NotFoundHttpException(__('error.not_found'));
|
||||
}
|
||||
|
||||
// 코드 변경 시 중복 체크
|
||||
if (isset($data['code']) && $data['code'] !== $code) {
|
||||
$exists = Product::query()
|
||||
->where('tenant_id', $tenantId)
|
||||
->where('code', $data['code'])
|
||||
->where('id', '!=', $product->id)
|
||||
->exists();
|
||||
|
||||
if ($exists) {
|
||||
throw new BadRequestHttpException(__('error.duplicate_code'));
|
||||
}
|
||||
}
|
||||
|
||||
$data['updated_by'] = $userId;
|
||||
$product->update($data);
|
||||
|
||||
return $product->refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* 품목 삭제 (Product 전용, Soft Delete)
|
||||
*
|
||||
* @param string $code 품목 코드
|
||||
*/
|
||||
public function deleteItem(string $code): void
|
||||
{
|
||||
$tenantId = $this->tenantId();
|
||||
|
||||
$product = Product::query()
|
||||
->where('tenant_id', $tenantId)
|
||||
->where('code', $code)
|
||||
->first();
|
||||
|
||||
if (! $product) {
|
||||
throw new NotFoundHttpException(__('error.not_found'));
|
||||
}
|
||||
|
||||
$product->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* 품목 상세 조회 (code 기반, BOM 포함 옵션)
|
||||
*
|
||||
* @param string $code 품목 코드
|
||||
* @param bool $includeBom BOM 포함 여부
|
||||
*/
|
||||
public function getItemByCode(string $code, bool $includeBom = false): Product
|
||||
{
|
||||
$tenantId = $this->tenantId();
|
||||
|
||||
$query = Product::query()
|
||||
->with('category:id,name')
|
||||
->where('tenant_id', $tenantId)
|
||||
->where('code', $code);
|
||||
|
||||
if ($includeBom) {
|
||||
$query->with('componentLines.childProduct:id,code,name,unit');
|
||||
}
|
||||
|
||||
$product = $query->first();
|
||||
|
||||
if (! $product) {
|
||||
throw new NotFoundHttpException(__('error.not_found'));
|
||||
}
|
||||
|
||||
return $product;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user