'decimal:6', 'created_at' => 'datetime', 'updated_at' => 'datetime', 'deleted_at' => 'datetime', ]; protected $hidden = [ 'deleted_at', ]; /** * 상위 제품 (모델/제품) */ public function parentProduct() { return $this->belongsTo(Product::class, 'parent_product_id'); } /** * 참조된 제품 또는 자재를 동적으로 가져오기 * ref_type에 따라 Product 또는 Material을 반환 */ public function referencedItem() { if ($this->ref_type === 'PRODUCT') { return $this->belongsTo(Product::class, 'ref_id'); } elseif ($this->ref_type === 'MATERIAL') { return $this->belongsTo(Material::class, 'ref_id'); } return null; } /** * 하위 제품 (ref_type = PRODUCT일 때만) */ public function product() { return $this->belongsTo(Product::class, 'ref_id') ->where('ref_type', 'PRODUCT'); } /** * 하위 자재 (ref_type = MATERIAL일 때만) */ public function material() { return $this->belongsTo(Material::class, 'ref_id') ->where('ref_type', 'MATERIAL'); } // --------------------------------------------------- // 🔎 Query Scopes // --------------------------------------------------- /** * 제품 BOM 아이템만 */ public function scopeProducts($query) { return $query->where('ref_type', 'PRODUCT'); } /** * 자재 BOM 아이템만 */ public function scopeMaterials($query) { return $query->where('ref_type', 'MATERIAL'); } /** * 특정 상위 제품의 BOM */ public function scopeForParent($query, int $parentProductId) { return $query->where('parent_product_id', $parentProductId); } }