chore: update document approval workflow and bug fixes

This commit is contained in:
2026-05-25 13:05:20 +08:00
parent d573c02893
commit 39a8e1d4cd
910 changed files with 49994 additions and 1010 deletions

View File

@@ -0,0 +1,56 @@
<?php
namespace Modules\DocumentManagement\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Modules\DocumentManagement\Models\Document;
use Illuminate\Support\Facades\Gate;
class DocumentApprovalController extends Controller
{
/**
* Approve or reject a document.
*/
public function __invoke(Request $request, Document $document)
{
// Typically, we would use a Gate or Policy.
// For Contractor Admin, they should have a specific role or permission.
// Assuming there is a policy checking user->hasRole('Contractor Admin') or similar.
Gate::authorize('approve', $document);
$validated = $request->validate([
'status' => 'required|in:Approved,Rejected',
'comments' => 'nullable|string|max:1000',
]);
// Find the global approval chain if it exists
$chain = \Modules\ApprovalWorkflow\Models\ApprovalChain::where('approvable_type', Document::class)
->where('approvable_id', $document->id)
->whereIn('status', ['pending', 'in_review'])
->first();
if ($chain) {
$service = app(\Modules\ApprovalWorkflow\Services\ApprovalService::class);
if ($validated['status'] === 'Approved') {
$service->approve($chain, $request->user(), $validated['comments']);
} else {
$service->reject($chain, $request->user(), $validated['comments']);
}
} else {
// Fallback for older documents that didn't go through the ApprovalWorkflow
$document->approvals()->create([
'approved_by' => $request->user()->id,
'status' => $validated['status'],
'comments' => $validated['comments'] ?? null,
'approved_at' => now(),
]);
$document->update([
'status' => $validated['status'],
]);
}
return back()->with('success', "Document has been {$validated['status']}.");
}
}

View File

@@ -0,0 +1,192 @@
<?php
namespace Modules\DocumentManagement\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Inertia\Inertia;
use Modules\DocumentManagement\Models\Document;
use Modules\DocumentManagement\Models\DocumentCategory;
use Modules\ProjectManagement\Models\Project;
class DocumentController extends Controller
{
public function index(Request $request)
{
$query = Document::with(['uploader:id,name', 'category', 'project', 'approvals.approver']);
if ($search = $request->search) {
$query->where('title', 'like', "%{$search}%");
}
if ($categoryId = $request->category_id) {
$query->where('category_id', $categoryId);
}
if ($projectId = $request->project_id) {
$query->where('project_id', $projectId);
}
if ($status = $request->status) {
$query->where('status', $status);
}
if ($type = $request->documentable_type) {
$query->where('documentable_type', $type);
}
$documents = $query->latest()->paginate(20)->withQueryString();
$categories = DocumentCategory::all();
$projects = Project::select('id', 'name')->get();
return Inertia::render('DocumentManagement::Documents/Index', [
'documents' => $documents,
'categories' => $categories,
'projects' => $projects,
'filters' => $request->only(['search', 'category_id', 'project_id', 'status', 'documentable_type']),
]);
}
public function upload(Request $request)
{
$validated = $request->validate([
'title' => 'required|string|max:255',
'category_id' => 'required|exists:document_categories,id',
'project_id' => 'nullable|exists:projects,id',
'description' => 'nullable|string',
'documentable_type' => 'nullable|string',
'documentable_id' => 'nullable|integer',
'file' => 'required|file|max:51200|mimes:pdf,jpg,jpeg,png,doc,docx,xls,xlsx,dwg',
]);
$file = $request->file('file');
$category = DocumentCategory::find($validated['category_id']);
$path = $file->store("documents/" . str()->slug($category->name), 'local');
$document = Document::create([
'title' => $validated['title'],
'category_id' => $validated['category_id'],
'project_id' => $validated['project_id'] ?? null,
'description' => $validated['description'] ?? null,
'documentable_type' => $validated['documentable_type'] ?? null,
'documentable_id' => $validated['documentable_id'] ?? null,
'status' => 'Pending',
'uploaded_by' => $request->user()->id,
'current_file_path' => $path,
'current_file_name' => $file->getClientOriginalName(),
'mime_type' => $file->getMimeType(),
'file_size' => $file->getSize(),
'version_count' => 1,
]);
// Create initial version
$document->versions()->create([
'version_number' => 1,
'file_path' => $path,
'file_name' => $file->getClientOriginalName(),
'mime_type' => $file->getMimeType(),
'file_size' => $file->getSize(),
'uploaded_by' => $request->user()->id,
'change_notes' => 'Initial upload',
]);
// Trigger Global Approval Workflow
$approverIds = \App\Models\User::role(['Main Contractor Admin'])->pluck('id')->toArray();
if (empty($approverIds)) {
$approverIds = \App\Models\User::role('Super Admin')->pluck('id')->toArray();
}
if (!empty($approverIds)) {
app(\Modules\ApprovalWorkflow\Services\ApprovalService::class)->createChain(
$document,
$approverIds,
'document',
$request->user()->id,
"New document uploaded: {$document->title}"
);
}
return back()->with('success', 'Document uploaded successfully and is pending approval.');
}
public function uploadVersion(Request $request, Document $document)
{
$validated = $request->validate([
'file' => 'required|file|max:51200|mimes:pdf,jpg,jpeg,png,doc,docx,xls,xlsx,dwg',
'change_notes' => 'nullable|string|max:500',
]);
$file = $request->file('file');
$category = $document->category;
$path = $file->store("documents/" . str()->slug($category->name), 'local');
$document->addVersion(
$path,
$file->getClientOriginalName(),
$file->getMimeType(),
$file->getSize(),
$request->user()->id,
$validated['change_notes'] ?? null,
);
// Reset status to Pending when a new version is uploaded
$document->update(['status' => 'Pending']);
// Trigger Global Approval Workflow for the new version
$approverIds = \App\Models\User::role(['Main Contractor Admin'])->pluck('id')->toArray();
if (empty($approverIds)) {
$approverIds = \App\Models\User::role('Super Admin')->pluck('id')->toArray();
}
if (!empty($approverIds)) {
app(\Modules\ApprovalWorkflow\Services\ApprovalService::class)->createChain(
$document,
$approverIds,
'document',
$request->user()->id,
"New version uploaded for: {$document->title}"
);
}
return back()->with('success', 'New version uploaded. Document status reset to Pending.');
}
public function download(Document $document)
{
if (!$document->current_file_path || !Storage::disk('local')->exists($document->current_file_path)) {
return back()->with('error', 'File not found.');
}
return Storage::disk('local')->download($document->current_file_path, $document->current_file_name);
}
public function downloadVersion(Document $document, int $versionId)
{
$version = $document->versions()->findOrFail($versionId);
if (!Storage::disk('local')->exists($version->file_path)) {
return back()->with('error', 'Version file not found.');
}
return Storage::disk('local')->download($version->file_path, $version->file_name);
}
public function versions(Document $document)
{
$document->load(['versions.uploader:id,name', 'uploader:id,name', 'approvals.approver']);
return Inertia::render('DocumentManagement::Documents/Versions', [
'document' => $document,
]);
}
public function destroy(Document $document)
{
// Delete all version files
foreach ($document->versions as $version) {
Storage::disk('local')->delete($version->file_path);
}
if ($document->current_file_path) {
Storage::disk('local')->delete($document->current_file_path);
}
$document->delete();
return back()->with('success', 'Document deleted.');
}
}

View File

@@ -0,0 +1,56 @@
<?php
namespace Modules\DocumentManagement\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class DocumentManagementController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
return view('documentmanagement::index');
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
return view('documentmanagement::create');
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request) {}
/**
* Show the specified resource.
*/
public function show($id)
{
return view('documentmanagement::show');
}
/**
* Show the form for editing the specified resource.
*/
public function edit($id)
{
return view('documentmanagement::edit');
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, $id) {}
/**
* Remove the specified resource from storage.
*/
public function destroy($id) {}
}