feat: [quality] 품질관리서 파일 업로드/삭제 API
- POST /{id}/upload-file: 1건당 1파일, 기존 파일 교체
- DELETE /{id}/file: 파일 soft delete
- QualityDocument.file() relation 추가
- R2 저장 경로: {tenant_id}/quality-documents/{year}/{month}
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\Commons\File;
|
||||
use App\Models\Documents\Document;
|
||||
use App\Models\Documents\DocumentData;
|
||||
use App\Models\Documents\DocumentTemplate;
|
||||
@@ -13,7 +14,9 @@
|
||||
use App\Models\Qualitys\QualityDocumentLocation;
|
||||
use App\Models\Qualitys\QualityDocumentOrder;
|
||||
use App\Services\Audit\AuditLogger;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
@@ -1248,4 +1251,78 @@ private function formatInspectionPeriod(array $options): string
|
||||
|
||||
return $start ?: $end ?: '';
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 파일 업로드/삭제
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* 품질관리서 파일 업로드 (1건당 1파일, 기존 파일 있으면 교체)
|
||||
*/
|
||||
public function uploadFile(int $id, UploadedFile $uploadedFile): array
|
||||
{
|
||||
$tenantId = $this->tenantId();
|
||||
$userId = $this->apiUserId();
|
||||
|
||||
$doc = QualityDocument::where('tenant_id', $tenantId)->findOrFail($id);
|
||||
|
||||
// 기존 파일이 있으면 물리 삭제 (교체)
|
||||
$existingFile = $doc->file;
|
||||
if ($existingFile) {
|
||||
$existingFile->permanentDelete();
|
||||
}
|
||||
|
||||
// 저장 경로: {tenant_id}/quality-documents/{year}/{month}/{stored_name}
|
||||
$date = now();
|
||||
$storedName = bin2hex(random_bytes(16)).'.'.$uploadedFile->getClientOriginalExtension();
|
||||
$filePath = sprintf(
|
||||
'%d/quality-documents/%s/%s/%s',
|
||||
$tenantId,
|
||||
$date->format('Y'),
|
||||
$date->format('m'),
|
||||
$storedName
|
||||
);
|
||||
|
||||
// R2에 파일 저장
|
||||
Storage::disk('r2')->put($filePath, file_get_contents($uploadedFile->getPathname()));
|
||||
|
||||
// DB 레코드 생성
|
||||
$file = File::create([
|
||||
'tenant_id' => $tenantId,
|
||||
'document_type' => QualityDocument::class,
|
||||
'document_id' => $doc->id,
|
||||
'display_name' => $uploadedFile->getClientOriginalName(),
|
||||
'stored_name' => $storedName,
|
||||
'file_path' => $filePath,
|
||||
'file_size' => $uploadedFile->getSize(),
|
||||
'mime_type' => $uploadedFile->getClientMimeType(),
|
||||
'uploaded_by' => $userId,
|
||||
'created_by' => $userId,
|
||||
]);
|
||||
|
||||
return [
|
||||
'id' => $file->id,
|
||||
'display_name' => $file->display_name,
|
||||
'file_size' => $file->file_size,
|
||||
'mime_type' => $file->mime_type,
|
||||
'created_at' => $file->created_at?->toIso8601String(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 품질관리서 파일 삭제
|
||||
*/
|
||||
public function deleteFile(int $id): void
|
||||
{
|
||||
$tenantId = $this->tenantId();
|
||||
|
||||
$doc = QualityDocument::where('tenant_id', $tenantId)->findOrFail($id);
|
||||
|
||||
$file = $doc->file;
|
||||
if (! $file) {
|
||||
throw new NotFoundHttpException(__('error.not_found'));
|
||||
}
|
||||
|
||||
$file->softDeleteFile($this->apiUserId());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user