feat: [approval] 지출결의서 첨부파일 업로드/다운로드 기능 추가
- 첨부파일 업로드 API (GCS 연동, 20MB 제한) - 첨부파일 삭제/다운로드 API 추가 - 지출결의서 폼에 드래그&드롭 멀티 파일 업로드 UI 추가 - ApprovalService에 linkAttachments 메서드 추가 (is_temp 플래그 관리) - show 페이지에 첨부파일 목록 표시 및 다운로드 링크 - 지출부서 기본값 '본사', 로그인 사용자 이름 자동입력, 제목 필드 제거
This commit is contained in:
@@ -3,9 +3,13 @@
|
||||
namespace App\Http\Controllers\Api\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Boards\File;
|
||||
use App\Services\ApprovalService;
|
||||
use App\Services\GoogleCloudStorageService;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class ApprovalApiController extends Controller
|
||||
{
|
||||
@@ -100,6 +104,8 @@ public function store(Request $request): JsonResponse
|
||||
'steps' => 'nullable|array',
|
||||
'steps.*.user_id' => 'required_with:steps|exists:users,id',
|
||||
'steps.*.step_type' => 'required_with:steps|in:approval,agreement,reference',
|
||||
'attachment_file_ids' => 'nullable|array',
|
||||
'attachment_file_ids.*' => 'integer',
|
||||
]);
|
||||
|
||||
$approval = $this->service->createApproval($request->all());
|
||||
@@ -124,6 +130,8 @@ public function update(Request $request, int $id): JsonResponse
|
||||
'steps' => 'nullable|array',
|
||||
'steps.*.user_id' => 'required_with:steps|exists:users,id',
|
||||
'steps.*.step_type' => 'required_with:steps|in:approval,agreement,reference',
|
||||
'attachment_file_ids' => 'nullable|array',
|
||||
'attachment_file_ids.*' => 'integer',
|
||||
]);
|
||||
|
||||
try {
|
||||
@@ -455,4 +463,94 @@ public function badgeCounts(): JsonResponse
|
||||
|
||||
return response()->json(['success' => true, 'data' => $counts]);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 첨부파일
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* 첨부파일 업로드
|
||||
*/
|
||||
public function uploadFile(Request $request, GoogleCloudStorageService $gcs): JsonResponse
|
||||
{
|
||||
$request->validate([
|
||||
'file' => 'required|file|max:20480',
|
||||
]);
|
||||
|
||||
$file = $request->file('file');
|
||||
$tenantId = session('selected_tenant_id');
|
||||
$storedName = Str::random(40).'.'.$file->getClientOriginalExtension();
|
||||
$storagePath = "approvals/{$tenantId}/{$storedName}";
|
||||
|
||||
Storage::disk('tenant')->put($storagePath, file_get_contents($file));
|
||||
|
||||
$gcsUri = null;
|
||||
$gcsObjectName = null;
|
||||
if ($gcs->isAvailable()) {
|
||||
$gcsObjectName = $storagePath;
|
||||
$gcsUri = $gcs->upload($file->getRealPath(), $gcsObjectName);
|
||||
}
|
||||
|
||||
$fileRecord = File::create([
|
||||
'tenant_id' => $tenantId,
|
||||
'document_type' => 'approval_attachment',
|
||||
'original_name' => $file->getClientOriginalName(),
|
||||
'stored_name' => $storedName,
|
||||
'file_path' => $storagePath,
|
||||
'mime_type' => $file->getMimeType(),
|
||||
'file_size' => $file->getSize(),
|
||||
'file_type' => strtolower($file->getClientOriginalExtension()),
|
||||
'gcs_object_name' => $gcsObjectName,
|
||||
'gcs_uri' => $gcsUri,
|
||||
'is_temp' => true,
|
||||
'uploaded_by' => auth()->id(),
|
||||
'created_by' => auth()->id(),
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => [
|
||||
'id' => $fileRecord->id,
|
||||
'name' => $fileRecord->original_name,
|
||||
'size' => $fileRecord->file_size,
|
||||
'mime_type' => $fileRecord->mime_type,
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 첨부파일 삭제
|
||||
*/
|
||||
public function deleteFile(int $fileId): JsonResponse
|
||||
{
|
||||
$file = File::where('id', $fileId)
|
||||
->where('uploaded_by', auth()->id())
|
||||
->first();
|
||||
|
||||
if (! $file) {
|
||||
return response()->json(['success' => false, 'message' => '파일을 찾을 수 없습니다.'], 404);
|
||||
}
|
||||
|
||||
if ($file->existsInStorage()) {
|
||||
Storage::disk('tenant')->delete($file->file_path);
|
||||
}
|
||||
|
||||
$file->forceDelete();
|
||||
|
||||
return response()->json(['success' => true, 'message' => '파일이 삭제되었습니다.']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 첨부파일 다운로드
|
||||
*/
|
||||
public function downloadFile(int $fileId)
|
||||
{
|
||||
$file = File::findOrFail($fileId);
|
||||
|
||||
if (Storage::disk('tenant')->exists($file->file_path)) {
|
||||
return Storage::disk('tenant')->download($file->file_path, $file->original_name);
|
||||
}
|
||||
|
||||
abort(404, '파일을 찾을 수 없습니다.');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user