Files
sam-api/app/Models/Products/ProductComponent.php
hskwon d5bfb24ef9 feat: BP-MES Phase 1 - products/product_components 테이블 확장
- products 테이블에 33개 필드 추가
  - 공통: is_active, margin_rate, costs, safety_stock, lead_time, is_variable_size
  - FG 전용: product_category, lot_abbreviation, note
  - PT 전용: part_type, part_usage, installation_type, assembly_type,
    side_spec_width, side_spec_height, assembly_length,
    guide_rail_model_type, guide_rail_model
  - 절곡품: bending_diagram, bending_details, material, length, bending_length
  - 인증: certification_number, start/end_date, specification/certification files
  - 동적 확장: options (JSON)

- product_components 테이블에 5개 필드 추가
  - 수식 계산: quantity_formula
  - 조건부 BOM: condition
  - 절곡품: is_bending, bending_diagram, bending_details

- Product/ProductComponent 모델 fillable/casts 업데이트
- 인덱스 추가: is_active, product_category, part_type, part_usage, is_bending
2025-11-14 09:07:33 +09:00

120 lines
2.8 KiB
PHP

<?php
namespace App\Models\Products;
use App\Models\Materials\Material;
use App\Traits\BelongsToTenant;
use App\Traits\ModelTrait;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class ProductComponent extends Model
{
use BelongsToTenant, ModelTrait, SoftDeletes;
protected $table = 'product_components';
protected $fillable = [
'tenant_id',
'parent_product_id',
'category_id',
'category_name',
'ref_type',
'ref_id',
'quantity',
'sort_order',
// BP-MES: 수식 계산 및 조건부 BOM
'quantity_formula',
'condition',
// BP-MES: 절곡품
'is_bending',
'bending_diagram',
'bending_details',
'created_by',
'updated_by',
];
protected $casts = [
'quantity' => 'decimal:6',
'created_at' => 'datetime',
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
// BP-MES: 추가 타입 캐스팅
'is_bending' => 'boolean',
'bending_details' => 'array',
];
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);
}
}