ultimatepos/Modules/QualityManagement/Services/SpcAnalysisService.php

93 lines
2.8 KiB
PHP

<?php
namespace Modules\QualityManagement\Services;
use Modules\QualityManagement\Models\SpcMeasurement;
class SpcAnalysisService
{
public function recordMeasurement(int $businessId, array $data): SpcMeasurement
{
$inControl = $this->isInControl(
(float) $data['measured_value'],
isset($data['usl']) ? (float) $data['usl'] : null,
isset($data['lsl']) ? (float) $data['lsl'] : null
);
return SpcMeasurement::create(array_merge($data, [
'business_id' => $businessId,
'measured_at' => $data['measured_at'] ?? now(),
'in_control' => $inControl,
'recorded_by' => $data['recorded_by'] ?? auth()->id(),
]));
}
public function isInControl(float $value, ?float $usl, ?float $lsl): bool
{
if ($usl !== null && $value > $usl) {
return false;
}
if ($lsl !== null && $value < $lsl) {
return false;
}
return true;
}
public function characteristicSummary(int $businessId, string $characteristic, int $days = 30): array
{
$measurements = SpcMeasurement::forBusiness($businessId)
->where('characteristic_name', $characteristic)
->where('measured_at', '>=', now()->subDays($days))
->orderBy('measured_at')
->get();
if ($measurements->isEmpty()) {
return ['count' => 0, 'mean' => 0, 'min' => 0, 'max' => 0, 'out_of_control' => 0];
}
$values = $measurements->pluck('measured_value')->map(fn ($v) => (float) $v);
return [
'count' => $measurements->count(),
'mean' => round($values->avg(), 4),
'min' => round($values->min(), 4),
'max' => round($values->max(), 4),
'out_of_control' => $measurements->where('in_control', false)->count(),
'cpk_estimate' => $this->estimateCpk($values, $measurements->first()),
];
}
protected function estimateCpk($values, SpcMeasurement $sample): ?float
{
$usl = $sample->usl;
$lsl = $sample->lsl;
if ($usl === null || $lsl === null || $values->count() < 2) {
return null;
}
$mean = $values->avg();
$std = $this->stdDev($values->all());
if ($std <= 0) {
return null;
}
$cpu = ($usl - $mean) / (3 * $std);
$cpl = ($mean - $lsl) / (3 * $std);
return round(min($cpu, $cpl), 3);
}
protected function stdDev(array $values): float
{
$n = count($values);
if ($n < 2) {
return 0;
}
$mean = array_sum($values) / $n;
$variance = array_sum(array_map(fn ($v) => ($v - $mean) ** 2, $values)) / ($n - 1);
return sqrt($variance);
}
}