211 lines
6.9 KiB
PHP
211 lines
6.9 KiB
PHP
<?php
|
|
|
|
namespace Modules\Investment\Http\Controllers;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Services\DocumentService;
|
|
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Http\UploadedFile;
|
|
use Modules\Investment\Entities\Investment;
|
|
use Modules\Investment\Http\Requests\ManualInvestmentRequest;
|
|
use Modules\Investment\Services\InvestmentPostingService;
|
|
use Modules\Investment\Services\InvestmentSummaryService;
|
|
use Modules\Investment\Transformers\InvestmentResource;
|
|
use Symfony\Component\HttpFoundation\StreamedResponse;
|
|
|
|
class InvestmentController extends Controller
|
|
{
|
|
use AuthorizesRequests;
|
|
|
|
public function __construct(
|
|
protected InvestmentPostingService $postingService,
|
|
protected InvestmentSummaryService $summaryService,
|
|
protected DocumentService $documentService,
|
|
) {}
|
|
|
|
public function summary(Request $request): JsonResponse
|
|
{
|
|
$this->authorize('viewOwnSummary', Investment::class);
|
|
|
|
$summary = $this->summaryService->getMemberSummary($request->user()->id);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => $summary,
|
|
'message' => 'Ringkasan pelaburan berjaya dimuatkan',
|
|
]);
|
|
}
|
|
|
|
public function index(Request $request): JsonResponse
|
|
{
|
|
$this->authorize('viewAny', Investment::class);
|
|
|
|
$perPage = min((int) $request->get('per_page', 10), 1000);
|
|
$sortBy = (string) $request->get('sort_by', 'created_at');
|
|
$sortOrder = strtolower((string) $request->get('sort_order', 'desc')) === 'asc' ? 'asc' : 'desc';
|
|
|
|
$allowedSort = [
|
|
'created_at',
|
|
'amount',
|
|
'status',
|
|
'source',
|
|
'reference_no',
|
|
'completed_at',
|
|
];
|
|
if (! in_array($sortBy, $allowedSort, true)) {
|
|
$sortBy = 'created_at';
|
|
}
|
|
|
|
$query = Investment::query()
|
|
->with([
|
|
'user:id,name,email,ic_number,member_number',
|
|
'investmentType:id,code,name',
|
|
])
|
|
->orderBy($sortBy, $sortOrder);
|
|
|
|
if ($search = trim((string) $request->get('search', ''))) {
|
|
$query->where(function ($q) use ($search) {
|
|
$q->where('reference_no', 'ILIKE', "%{$search}%")
|
|
->orWhere('remarks', 'ILIKE', "%{$search}%")
|
|
->orWhereHas('user', function ($userQuery) use ($search) {
|
|
$userQuery->where('name', 'ILIKE', "%{$search}%")
|
|
->orWhere('email', 'ILIKE', "%{$search}%")
|
|
->orWhere('ic_number', 'ILIKE', "%{$search}%");
|
|
})
|
|
->orWhereHas('investmentType', function ($typeQuery) use ($search) {
|
|
$typeQuery->where('name', 'ILIKE', "%{$search}%")
|
|
->orWhere('code', 'ILIKE', "%{$search}%");
|
|
});
|
|
});
|
|
}
|
|
|
|
if ($status = $request->query('status')) {
|
|
$query->where('status', $status);
|
|
}
|
|
|
|
if ($source = $request->query('source')) {
|
|
$query->where('source', $source);
|
|
}
|
|
|
|
if ($userId = $request->query('user_id')) {
|
|
$query->where('user_id', $userId);
|
|
}
|
|
|
|
if ($typeId = $request->query('investment_type_id')) {
|
|
$query->where('investment_type_id', $typeId);
|
|
}
|
|
|
|
$investments = $query->paginate($perPage);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => InvestmentResource::collection($investments->items()),
|
|
'pagination' => [
|
|
'current_page' => $investments->currentPage(),
|
|
'per_page' => $investments->perPage(),
|
|
'total' => $investments->total(),
|
|
'last_page' => $investments->lastPage(),
|
|
'from' => $investments->firstItem(),
|
|
'to' => $investments->lastItem(),
|
|
'has_more_pages' => $investments->hasMorePages(),
|
|
],
|
|
'message' => 'Pelaburan berjaya dimuatkan',
|
|
]);
|
|
}
|
|
|
|
public function show(string $id): JsonResponse
|
|
{
|
|
$this->authorize('view', Investment::class);
|
|
|
|
$investment = Investment::query()
|
|
->with([
|
|
'user:id,name,email,ic_number,member_number',
|
|
'account',
|
|
'investmentType',
|
|
'createdBy:id,name,email',
|
|
'approvedBy:id,name,email',
|
|
'ledgerEntries',
|
|
'payment.billplzTransaction',
|
|
'documents',
|
|
])
|
|
->find($id);
|
|
|
|
if (! $investment) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Pelaburan tidak dijumpai.',
|
|
], 404);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => new InvestmentResource($investment),
|
|
'message' => 'Pelaburan berjaya dimuatkan',
|
|
]);
|
|
}
|
|
|
|
public function storeManual(ManualInvestmentRequest $request): JsonResponse
|
|
{
|
|
$this->authorize('createManual', Investment::class);
|
|
|
|
$validated = $request->validated();
|
|
$documents = collect($request->file('documents', []))
|
|
->filter(fn ($file) => $file instanceof UploadedFile)
|
|
->values()
|
|
->all();
|
|
|
|
$investment = $this->postingService->postManualInvestment(
|
|
$validated['user_id'],
|
|
$validated['investment_type_id'],
|
|
$validated['amount'],
|
|
$validated['remarks'] ?? null,
|
|
$request->user(),
|
|
);
|
|
|
|
foreach ($documents as $file) {
|
|
$this->documentService->validateFile($file);
|
|
$this->documentService->uploadDocument($investment, $file, 'attachment');
|
|
}
|
|
|
|
$investment->loadMissing([
|
|
'user:id,name,email,ic_number,member_number',
|
|
'investmentType:id,code,name',
|
|
'account',
|
|
'documents',
|
|
]);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => new InvestmentResource($investment),
|
|
'message' => 'Pelaburan manual berjaya direkodkan',
|
|
], 201);
|
|
}
|
|
|
|
public function downloadDocument(string $id, string $documentId): StreamedResponse|JsonResponse
|
|
{
|
|
$this->authorize('view', Investment::class);
|
|
|
|
$investment = Investment::query()->find($id);
|
|
|
|
if (! $investment) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Pelaburan tidak dijumpai.',
|
|
], 404);
|
|
}
|
|
|
|
$document = $investment->documents()->find($documentId);
|
|
|
|
if (! $document) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Dokumen tidak dijumpai.',
|
|
], 404);
|
|
}
|
|
|
|
return $this->documentService->downloadDocument($document->id);
|
|
}
|
|
}
|