ultimatepos/Modules/AssetExchange/Http/Controllers/AppraisalController.php

290 lines
10 KiB
PHP

<?php
namespace Modules\AssetExchange\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Response;
use Modules\AssetExchange\Http\Controllers\Concerns\AuthorizesAssetExchange;
use Modules\AssetExchange\Models\Appraisal;
use Modules\AssetExchange\Models\Listing;
use Modules\AssetExchange\Services\AppraisalService;
use Modules\AssetExchange\Utils\AssetExchangeUtil;
use Yajra\DataTables\Facades\DataTables;
class AppraisalController extends Controller
{
use AuthorizesAssetExchange;
public function __construct(
protected AssetExchangeUtil $aexUtil,
protected AppraisalService $appraisalService
) {
}
public function index(Request $request)
{
$this->authorizeAexAccess('aex.appraisals.view');
$business_id = $this->aexUtil->getBusinessId();
if ($request->ajax()) {
$query = Appraisal::where('business_id', $business_id)
->with(['listing:id,title,listing_code', 'appraiser:id,first_name,last_name,surname'])
->orderByDesc('created_at');
if ($status = $request->get('status')) {
$query->where('status', $status);
}
return DataTables::of($query)
->addColumn('listing_title', fn ($row) => $row->listing?->title ?? '—')
->addColumn('listing_code', fn ($row) => $row->listing?->listing_code ?? '—')
->addColumn('appraiser_name', fn ($row) => $row->appraiser?->user_full_name ?? $row->appraiser?->first_name ?? '—')
->addColumn('status_label', fn ($row) => $this->aexUtil->statusLabel($row->status))
->addColumn('as_is_fmt', fn ($row) => $this->aexUtil->formatMoney($row->as_is_value))
->addColumn('action', function ($row) {
$html = '<div class="btn-group">';
$html .= '<a href="'.action([self::class, 'show'], [$row->id]).'" class="btn btn-xs btn-info"><i class="fa fa-eye"></i></a>';
if (auth()->user()->can('aex.appraisals.update')) {
$html .= ' <a href="'.action([self::class, 'workspace'], [$row->id]).'" class="btn btn-xs btn-primary"><i class="fa fa-sitemap"></i></a>';
}
$html .= '</div>';
return $html;
})
->rawColumns(['action'])
->make(true);
}
return view('assetexchange::appraisals.index', [
'statuses' => $this->aexUtil->statusLabels(),
]);
}
public function create(Request $request)
{
$this->authorizeAexAccess('aex.appraisals.create');
$business_id = $this->aexUtil->getBusinessId();
$listing_id = $request->integer('listing_id') ?: null;
$listing = null;
if ($listing_id) {
$listing = Listing::where('business_id', $business_id)->findOrFail($listing_id);
}
$listings = Listing::where('business_id', $business_id)
->whereIn('status', ['submitted', 'under_review', 'appraised', 'in_deal'])
->orderByDesc('id')
->pluck('title', 'id');
return view('assetexchange::appraisals.create', compact('listing', 'listings'));
}
public function store(Request $request)
{
$this->authorizeAexAccess('aex.appraisals.create');
$business = $this->aexUtil->getBusiness();
if (! $business) {
abort(404);
}
$data = $request->validate([
'listing_id' => 'required|exists:aex_listings,id',
'methodology' => 'nullable|string|max:50',
'field_visit_date' => 'nullable|string',
'appraisal_fee' => 'nullable|integer|min:0',
'auto_import' => 'sometimes|boolean',
]);
$listing = Listing::where('business_id', $business->id)->findOrFail($data['listing_id']);
$options = [
'methodology' => $data['methodology'] ?? null,
'field_visit_date' => $this->aexUtil->parseInputDate($data['field_visit_date'] ?? null),
'appraisal_fee' => $data['appraisal_fee'] ?? null,
'auto_import' => $request->boolean('auto_import', true),
];
try {
$appraisal = $this->appraisalService->startAppraisal($business, $listing, auth()->user(), $options);
} catch (\Throwable $e) {
return $this->aexUtil->jsonOrRedirect($request, false, $e->getMessage());
}
return $this->aexUtil->jsonOrRedirect(
$request,
true,
__('assetexchange::lang.appraisal_started'),
action([self::class, 'workspace'], [$appraisal->id])
);
}
public function show($id)
{
$this->authorizeAexAccess('aex.appraisals.view');
$business_id = $this->aexUtil->getBusinessId();
$appraisal = Appraisal::where('business_id', $business_id)
->with(['listing.seller', 'appraiser', 'approvedByUser', 'lines'])
->findOrFail($id);
return view('assetexchange::appraisals.show', compact('appraisal'));
}
public function workspace($id)
{
$this->authorizeAexAccess('aex.appraisals.update');
$business_id = $this->aexUtil->getBusinessId();
$appraisal = Appraisal::where('business_id', $business_id)
->with(['listing', 'lines.childLines'])
->findOrFail($id);
$lineTree = $appraisal->lines->whereNull('parent_line_id');
return view('assetexchange::appraisals.workspace', compact('appraisal', 'lineTree'));
}
public function importIe(Request $request, $id)
{
$this->authorizeAexAccess('aex.appraisals.update');
$business_id = $this->aexUtil->getBusinessId();
$appraisal = Appraisal::where('business_id', $business_id)->findOrFail($id);
$data = $request->validate([
'bom_id' => 'nullable|integer',
'replace_existing' => 'sometimes|boolean',
]);
try {
$count = $this->appraisalService->importFromIeBom(
$appraisal,
$data['bom_id'] ?? null,
$request->boolean('replace_existing')
);
} catch (\Throwable $e) {
return $this->aexUtil->jsonOrRedirect($request, false, $e->getMessage());
}
return $this->aexUtil->jsonOrRedirect(
$request,
true,
__('assetexchange::lang.ie_imported', ['count' => $count]),
action([self::class, 'workspace'], [$appraisal->id])
);
}
public function importCmms(Request $request, $id)
{
$this->authorizeAexAccess('aex.appraisals.update');
$business_id = $this->aexUtil->getBusinessId();
$appraisal = Appraisal::where('business_id', $business_id)->findOrFail($id);
$data = $request->validate([
'equipment_id' => 'nullable|integer',
'replace_existing' => 'sometimes|boolean',
]);
try {
$count = $this->appraisalService->importFromCmmsEquipmentParts(
$appraisal,
$data['equipment_id'] ?? null,
$request->boolean('replace_existing')
);
} catch (\Throwable $e) {
return $this->aexUtil->jsonOrRedirect($request, false, $e->getMessage());
}
return $this->aexUtil->jsonOrRedirect(
$request,
true,
__('assetexchange::lang.cmms_imported', ['count' => $count]),
action([self::class, 'workspace'], [$appraisal->id])
);
}
public function recalculate(Request $request, $id)
{
$this->authorizeAexAccess('aex.appraisals.update');
$business_id = $this->aexUtil->getBusinessId();
$appraisal = Appraisal::where('business_id', $business_id)->findOrFail($id);
try {
$appraisal = $this->appraisalService->recalculate($appraisal);
} catch (\Throwable $e) {
return $this->aexUtil->jsonOrRedirect($request, false, $e->getMessage());
}
return $this->aexUtil->jsonOrRedirect(
$request,
true,
__('assetexchange::lang.appraisal_recalculated'),
action([self::class, 'workspace'], [$appraisal->id])
);
}
public function approve(Request $request, $id)
{
$this->authorizeAexAccess('aex.appraisals.approve');
$business = $this->aexUtil->getBusiness();
$appraisal = Appraisal::where('business_id', $business->id)->findOrFail($id);
$data = $request->validate([
'report_summary' => 'nullable|string',
]);
try {
$appraisal = $this->appraisalService->approve(
$business,
$appraisal,
auth()->user(),
$data['report_summary'] ?? null
);
} catch (\Throwable $e) {
return $this->aexUtil->jsonOrRedirect($request, false, $e->getMessage());
}
return $this->aexUtil->jsonOrRedirect(
$request,
true,
__('assetexchange::lang.appraisal_approved'),
action([self::class, 'show'], [$appraisal->id])
);
}
public function report($id)
{
$this->authorizeAexAccess('aex.appraisals.view');
$business_id = $this->aexUtil->getBusinessId();
$appraisal = Appraisal::where('business_id', $business_id)->findOrFail($id);
$html = $this->appraisalService->generateReportHtml($appraisal);
return response($html)->header('Content-Type', 'text/html; charset=UTF-8');
}
public function reportPdf($id)
{
$this->authorizeAexAccess('aex.appraisals.view');
$business_id = $this->aexUtil->getBusinessId();
$appraisal = Appraisal::where('business_id', $business_id)->findOrFail($id);
$this->appraisalService->storeReportPdf($appraisal);
$pdfBinary = $this->appraisalService->renderReportPdf($appraisal->fresh());
$fileName = 'appraisal-'.$appraisal->appraisal_number.'.pdf';
return Response::make($pdfBinary, 200, [
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'attachment; filename="'.$fileName.'"',
]);
}
}