'date', 'production_qty' => 'integer', 'good_qty' => 'integer', 'defect_qty' => 'integer', 'defect_rate' => 'decimal:2', 'is_inspected' => 'boolean', 'is_packaged' => 'boolean', ]; protected $hidden = [ 'deleted_at', ]; // ────────────────────────────────────────────────────────────── // 상수 // ────────────────────────────────────────────────────────────── /** * 공정 유형 (WorkOrder와 동일) */ public const PROCESS_SCREEN = 'screen'; public const PROCESS_SLAT = 'slat'; public const PROCESS_BENDING = 'bending'; public const PROCESS_TYPES = [ self::PROCESS_SCREEN, self::PROCESS_SLAT, self::PROCESS_BENDING, ]; // ────────────────────────────────────────────────────────────── // 관계 // ────────────────────────────────────────────────────────────── /** * 작업지시 */ public function workOrder(): BelongsTo { return $this->belongsTo(WorkOrder::class); } /** * 작업지시 품목 */ public function workOrderItem(): BelongsTo { return $this->belongsTo(WorkOrderItem::class); } /** * 작업자 */ public function worker(): BelongsTo { return $this->belongsTo(User::class, 'worker_id'); } /** * 생성자 */ public function creator(): BelongsTo { return $this->belongsTo(User::class, 'created_by'); } /** * 수정자 */ public function updater(): BelongsTo { return $this->belongsTo(User::class, 'updated_by'); } // ────────────────────────────────────────────────────────────── // 스코프 // ────────────────────────────────────────────────────────────── /** * 공정유형별 필터 */ public function scopeProcessType($query, string $type) { return $query->where('process_type', $type); } /** * 작업일 범위 필터 */ public function scopeWorkDateBetween($query, $from, $to) { return $query->whereBetween('work_date', [$from, $to]); } /** * 작업지시별 필터 */ public function scopeWorkOrder($query, int $workOrderId) { return $query->where('work_order_id', $workOrderId); } /** * 작업자별 필터 */ public function scopeWorker($query, int $workerId) { return $query->where('worker_id', $workerId); } /** * 검사 완료 필터 */ public function scopeInspected($query) { return $query->where('is_inspected', true); } /** * 포장 완료 필터 */ public function scopePackaged($query) { return $query->where('is_packaged', true); } /** * 불량 있음 */ public function scopeHasDefects($query) { return $query->where('defect_qty', '>', 0); } // ────────────────────────────────────────────────────────────── // 헬퍼 메서드 // ────────────────────────────────────────────────────────────── /** * 불량률 계산 */ public function calculateDefectRate(): float { if ($this->production_qty <= 0) { return 0; } return round(($this->defect_qty / $this->production_qty) * 100, 2); } /** * 불량률 업데이트 */ public function updateDefectRate(): void { $this->defect_rate = $this->calculateDefectRate(); } /** * 양품수량 자동 계산 및 설정 */ public function calculateGoodQty(): int { return max(0, $this->production_qty - $this->defect_qty); } /** * 불량이 있는지 확인 */ public function hasDefects(): bool { return $this->defect_qty > 0; } /** * 검사 및 포장 모두 완료인지 확인 */ public function isFullyProcessed(): bool { return $this->is_inspected && $this->is_packaged; } // ────────────────────────────────────────────────────────────── // 부팅 // ────────────────────────────────────────────────────────────── protected static function boot() { parent::boot(); // 저장 전 불량률 자동 계산 static::saving(function (WorkResult $model) { $model->updateDefectRate(); }); } }