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

264 lines
10 KiB
PHP

<?php
namespace Modules\AssetExchange\Http\Controllers;
use App\User;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Modules\AssetExchange\Http\Controllers\Concerns\AuthorizesAssetExchange;
use Modules\AssetExchange\Models\Listing;
use Modules\AssetExchange\Services\ListingService;
use Modules\AssetExchange\Utils\AssetExchangeUtil;
use Yajra\DataTables\Facades\DataTables;
class ListingController extends Controller
{
use AuthorizesAssetExchange;
public function __construct(
protected AssetExchangeUtil $aexUtil,
protected ListingService $listingService
) {
}
public function index(Request $request)
{
$this->authorizeAexAccess('aex.listings.view');
$business_id = $this->aexUtil->getBusinessId();
if ($request->ajax()) {
$filters = $request->only([
'status', 'listing_type', 'scope_type', 'seller_contact_id',
'assigned_broker_user_id', 'visibility', 'search',
]);
$query = $this->listingService->listQuery($business_id, $filters);
return DataTables::of($query)
->addColumn('seller_name', fn ($row) => $row->seller?->name ?? '—')
->addColumn('broker_name', fn ($row) => $row->broker?->user_full_name ?? $row->broker?->first_name ?? '—')
->addColumn('type_label', fn ($row) => $this->aexUtil->listingTypeLabel($row->listing_type))
->addColumn('status_label', fn ($row) => $this->aexUtil->statusLabel($row->status))
->addColumn('asking_price_fmt', fn ($row) => $this->aexUtil->formatMoney($row->asking_price))
->addColumn('submitted_at_fmt', fn ($row) => $this->aexUtil->formatDateTime($row->submitted_at))
->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.listings.update') && ! in_array($row->status, ['sold', 'rejected', 'withdrawn'], true)) {
$html .= ' <a href="'.action([self::class, 'edit'], [$row->id]).'" class="btn btn-xs btn-primary"><i class="glyphicon glyphicon-edit"></i></a>';
}
if (auth()->user()->can('aex.listings.delete')) {
$html .= ' <button type="button" data-href="'.action([self::class, 'destroy'], [$row->id]).'" class="btn btn-xs btn-danger delete_aex_listing"><i class="glyphicon glyphicon-trash"></i></button>';
}
$html .= '</div>';
return $html;
})
->rawColumns(['action'])
->make(true);
}
return view('assetexchange::listings.index', [
'statuses' => $this->aexUtil->statusLabels(),
'listing_types' => $this->aexUtil->listingTypeLabels(),
'contacts' => $this->aexUtil->getContactsDropdown($business_id),
'brokers' => User::forDropdown($business_id, false, false, true),
]);
}
public function create()
{
$this->authorizeAexAccess('aex.listings.create');
$business_id = $this->aexUtil->getBusinessId();
return view('assetexchange::listings.create', [
'contacts' => $this->aexUtil->getContactsDropdown($business_id),
'listing_types' => $this->aexUtil->listingTypeLabels(),
]);
}
public function store(Request $request)
{
$this->authorizeAexAccess('aex.listings.create');
$business = $this->aexUtil->getBusiness();
if (! $business) {
abort(404);
}
$data = $request->validate([
'title' => 'required|string|max:255',
'listing_type' => 'required|in:machine_new,machine_used,production_line_full,production_line_partial,subsystem,spare_lot',
'scope_type' => 'sometimes|in:whole,partial,component',
'seller_contact_id' => 'nullable|exists:contacts,id',
'description' => 'nullable|string',
'location_text' => 'nullable|string|max:255',
'site_country' => 'nullable|string|max:100',
'year_manufactured' => 'nullable|integer|min:1900|max:2100',
'condition_grade' => 'nullable|string|max:50',
'asking_price' => 'nullable|integer|min:0',
'price_negotiable' => 'sometimes|boolean',
'visibility' => 'sometimes|in:internal,portal,public',
]);
$data['price_negotiable'] = $request->boolean('price_negotiable', true);
try {
$listing = $this->listingService->create($business, $data, auth()->user());
} catch (\Throwable $e) {
return $this->aexUtil->jsonOrRedirect($request, false, $e->getMessage());
}
return $this->aexUtil->jsonOrRedirect(
$request,
true,
__('assetexchange::lang.listing_created'),
action([self::class, 'show'], [$listing->id])
);
}
public function show($id)
{
$this->authorizeAexAccess('aex.listings.view');
$business_id = $this->aexUtil->getBusinessId();
$listing = Listing::where('business_id', $business_id)
->with(['seller', 'broker', 'appraisals', 'deals', 'offers', 'media', 'catalogMatches', 'researchCases', 'priceInquiries'])
->findOrFail($id);
$activeResearch = $listing->researchCases()
->whereIn('status', ['open', 'in_progress', 'review'])
->latest('id')
->first();
return view('assetexchange::listings.show', compact('listing', 'activeResearch'));
}
public function edit($id)
{
$this->authorizeAexAccess('aex.listings.update');
$business_id = $this->aexUtil->getBusinessId();
$listing = Listing::where('business_id', $business_id)->findOrFail($id);
if (in_array($listing->status, ['sold', 'rejected', 'withdrawn'], true)) {
abort(403, __('assetexchange::lang.listing_not_editable'));
}
return view('assetexchange::listings.edit', [
'listing' => $listing,
'contacts' => $this->aexUtil->getContactsDropdown($business_id),
'listing_types' => $this->aexUtil->listingTypeLabels(),
]);
}
public function update(Request $request, $id)
{
$this->authorizeAexAccess('aex.listings.update');
$business_id = $this->aexUtil->getBusinessId();
$listing = Listing::where('business_id', $business_id)->findOrFail($id);
$data = $request->validate([
'title' => 'sometimes|string|max:255',
'listing_type' => 'sometimes|in:machine_new,machine_used,production_line_full,production_line_partial,subsystem,spare_lot',
'scope_type' => 'sometimes|in:whole,partial,component',
'seller_contact_id' => 'nullable|exists:contacts,id',
'description' => 'nullable|string',
'location_text' => 'nullable|string|max:255',
'site_country' => 'nullable|string|max:100',
'year_manufactured' => 'nullable|integer|min:1900|max:2100',
'condition_grade' => 'nullable|string|max:50',
'asking_price' => 'nullable|integer|min:0',
'price_negotiable' => 'sometimes|boolean',
'visibility' => 'sometimes|in:internal,portal,public',
]);
if ($request->has('price_negotiable')) {
$data['price_negotiable'] = $request->boolean('price_negotiable');
}
try {
$listing = $this->listingService->update($listing, $data, auth()->user());
} catch (\Throwable $e) {
return $this->aexUtil->jsonOrRedirect($request, false, $e->getMessage());
}
return $this->aexUtil->jsonOrRedirect(
$request,
true,
__('assetexchange::lang.listing_updated'),
action([self::class, 'show'], [$listing->id])
);
}
public function destroy(Request $request, $id)
{
$this->authorizeAexAccess('aex.listings.delete');
$business_id = $this->aexUtil->getBusinessId();
$listing = Listing::where('business_id', $business_id)->findOrFail($id);
$listing->delete();
return $this->aexUtil->jsonOrRedirect(
$request,
true,
__('assetexchange::lang.listing_deleted'),
action([self::class, 'index'])
);
}
public function submit(Request $request, $id)
{
$this->authorizeAexAccess('aex.listings.update');
$business = $this->aexUtil->getBusiness();
$listing = Listing::where('business_id', $business->id)->findOrFail($id);
try {
$listing = $this->listingService->submit($business, $listing, auth()->user());
} catch (\Throwable $e) {
return $this->aexUtil->jsonOrRedirect($request, false, $e->getMessage());
}
return $this->aexUtil->jsonOrRedirect(
$request,
true,
__('assetexchange::lang.listing_submitted'),
action([self::class, 'show'], [$listing->id])
);
}
public function assignBroker(Request $request, $id)
{
$this->authorizeAexAccess('aex.listings.update');
$business = $this->aexUtil->getBusiness();
$listing = Listing::where('business_id', $business->id)->findOrFail($id);
$data = $request->validate([
'broker_user_id' => 'required|exists:users,id',
]);
try {
$listing = $this->listingService->assignBroker(
$business,
$listing,
(int) $data['broker_user_id'],
auth()->user()
);
} catch (\Throwable $e) {
return $this->aexUtil->jsonOrRedirect($request, false, $e->getMessage());
}
return $this->aexUtil->jsonOrRedirect(
$request,
true,
__('assetexchange::lang.broker_assigned'),
action([self::class, 'show'], [$listing->id])
);
}
}