264 lines
10 KiB
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])
|
|
);
|
|
}
|
|
}
|