120 lines
3.6 KiB
PHP
120 lines
3.6 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Design;
|
|
|
|
use App\Models\Design\DesignModel;
|
|
use App\Models\Design\ModelVersion;
|
|
use App\Services\Service;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Validation\ValidationException;
|
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|
|
|
class ModelVersionService extends Service
|
|
{
|
|
/** 특정 모델의 버전 목록 */
|
|
public function listByModel(int $modelId)
|
|
{
|
|
$tenantId = $this->tenantId();
|
|
|
|
$model = DesignModel::query()
|
|
->where('tenant_id', $tenantId)
|
|
->find($modelId);
|
|
|
|
if (! $model) {
|
|
throw new NotFoundHttpException(__('error.not_found'));
|
|
}
|
|
|
|
return ModelVersion::query()
|
|
->where('tenant_id', $tenantId)
|
|
->where('model_id', $modelId)
|
|
->orderBy('version_no')
|
|
->get();
|
|
}
|
|
|
|
/** DRAFT 생성 (version_no 자동/수동) */
|
|
public function createDraft(int $modelId, array $extra = []): ModelVersion
|
|
{
|
|
$tenantId = $this->tenantId();
|
|
|
|
$model = DesignModel::query()
|
|
->where('tenant_id', $tenantId)
|
|
->find($modelId);
|
|
|
|
if (! $model) {
|
|
throw new NotFoundHttpException(__('error.not_found'));
|
|
}
|
|
|
|
return DB::transaction(function () use ($tenantId, $model, $extra) {
|
|
$versionNo = $extra['version_no'] ?? null;
|
|
|
|
if ($versionNo === null) {
|
|
$max = ModelVersion::query()
|
|
->where('model_id', $model->id)
|
|
->max('version_no');
|
|
$versionNo = (int) ($max ?? 0) + 1;
|
|
} else {
|
|
$exists = ModelVersion::query()
|
|
->where('model_id', $model->id)
|
|
->where('version_no', $versionNo)
|
|
->exists();
|
|
if ($exists) {
|
|
throw ValidationException::withMessages(['version_no' => __('error.duplicate')]);
|
|
}
|
|
}
|
|
|
|
return ModelVersion::create([
|
|
'tenant_id' => $tenantId,
|
|
'model_id' => $model->id,
|
|
'version_no' => $versionNo,
|
|
'status' => 'DRAFT',
|
|
'is_active' => true,
|
|
'notes' => $extra['notes'] ?? null,
|
|
'effective_from' => $extra['effective_from'] ?? null,
|
|
'effective_to' => $extra['effective_to'] ?? null,
|
|
]);
|
|
});
|
|
}
|
|
|
|
/** RELEASED 전환 */
|
|
public function release(int $versionId): ModelVersion
|
|
{
|
|
$tenantId = $this->tenantId();
|
|
|
|
$mv = ModelVersion::query()
|
|
->where('tenant_id', $tenantId)
|
|
->find($versionId);
|
|
|
|
if (! $mv) {
|
|
throw new NotFoundHttpException(__('error.not_found'));
|
|
}
|
|
|
|
if ($mv->status === 'RELEASED') {
|
|
return $mv; // 멱등
|
|
}
|
|
|
|
// 릴리즈 전 유효성 검사
|
|
app(\App\Services\Design\BomTemplateService::class)->validateForRelease($mv->id);
|
|
|
|
$before = [
|
|
'status' => $mv->status,
|
|
'effective_from' => $mv->effective_from ? $mv->effective_from->toISOString() : null,
|
|
];
|
|
|
|
$mv->status = 'RELEASED';
|
|
$mv->effective_from = $mv->effective_from ?? now();
|
|
$mv->save();
|
|
|
|
// 감사 로그
|
|
app(\App\Services\Audit\AuditLogger::class)->log(
|
|
tenantId: $tenantId,
|
|
targetType: 'model_version',
|
|
targetId: $mv->id,
|
|
action: 'released',
|
|
before: $before,
|
|
after: ['status' => $mv->status, 'effective_from' => $mv->effective_from->toISOString()]
|
|
);
|
|
|
|
return $mv;
|
|
}
|
|
}
|