264 lines
9.3 KiB
PHP
264 lines
9.3 KiB
PHP
<?php
|
|
|
|
namespace Modules\AssetExchange\Http\Controllers;
|
|
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Routing\Controller;
|
|
use Modules\AssetExchange\Http\Controllers\Concerns\AuthorizesAssetExchange;
|
|
use Modules\AssetExchange\Models\Deal;
|
|
use Modules\AssetExchange\Models\Listing;
|
|
use Modules\AssetExchange\Services\AssetExchangeErpBridgeService;
|
|
use Modules\AssetExchange\Services\DealService;
|
|
use Modules\AssetExchange\Utils\AssetExchangeUtil;
|
|
use Yajra\DataTables\Facades\DataTables;
|
|
|
|
class DealController extends Controller
|
|
{
|
|
use AuthorizesAssetExchange;
|
|
|
|
public function __construct(
|
|
protected AssetExchangeUtil $aexUtil,
|
|
protected DealService $dealService,
|
|
protected AssetExchangeErpBridgeService $erpBridge
|
|
) {
|
|
}
|
|
|
|
public function index(Request $request)
|
|
{
|
|
$this->authorizeAexAccess('aex.deals.view');
|
|
|
|
$business_id = $this->aexUtil->getBusinessId();
|
|
|
|
if ($request->ajax()) {
|
|
$query = Deal::where('business_id', $business_id)
|
|
->with(['listing:id,title,listing_code', 'buyer:id,name', 'appraisal:id,appraisal_number'])
|
|
->orderByDesc('created_at');
|
|
|
|
if ($status = $request->get('status')) {
|
|
$query->where('status', $status);
|
|
}
|
|
if ($deal_type = $request->get('deal_type')) {
|
|
$query->where('deal_type', $deal_type);
|
|
}
|
|
|
|
return DataTables::of($query)
|
|
->addColumn('listing_title', fn ($row) => $row->listing?->title ?? '—')
|
|
->addColumn('buyer_name', fn ($row) => $row->buyer?->name ?? '—')
|
|
->addColumn('type_label', fn ($row) => $this->aexUtil->dealTypeLabel($row->deal_type))
|
|
->addColumn('status_label', fn ($row) => $this->aexUtil->statusLabel($row->status))
|
|
->addColumn('agreed_price_fmt', fn ($row) => $this->aexUtil->formatMoney($row->agreed_price))
|
|
->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>';
|
|
$html .= '</div>';
|
|
|
|
return $html;
|
|
})
|
|
->rawColumns(['action'])
|
|
->make(true);
|
|
}
|
|
|
|
return view('assetexchange::deals.index', [
|
|
'statuses' => $this->aexUtil->statusLabels(),
|
|
'deal_types' => $this->aexUtil->dealTypeLabels(),
|
|
]);
|
|
}
|
|
|
|
public function create(Request $request)
|
|
{
|
|
$this->authorizeAexAccess('aex.deals.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)
|
|
->with('appraisals')
|
|
->findOrFail($listing_id);
|
|
}
|
|
|
|
$listings = Listing::where('business_id', $business_id)
|
|
->whereIn('status', ['appraised', 'in_deal'])
|
|
->orderByDesc('id')
|
|
->pluck('title', 'id');
|
|
|
|
return view('assetexchange::deals.create', [
|
|
'listing' => $listing,
|
|
'listings' => $listings,
|
|
'deal_types' => $this->aexUtil->dealTypeLabels(),
|
|
'contacts' => $this->aexUtil->getContactsDropdown($business_id),
|
|
]);
|
|
}
|
|
|
|
public function store(Request $request)
|
|
{
|
|
$this->authorizeAexAccess('aex.deals.create');
|
|
|
|
$business = $this->aexUtil->getBusiness();
|
|
if (! $business) {
|
|
abort(404);
|
|
}
|
|
|
|
$data = $request->validate([
|
|
'listing_id' => 'required|exists:aex_listings,id',
|
|
'deal_type' => 'required|in:company_purchase,brokerage,appraisal_only,renovation_contract',
|
|
'buyer_contact_id' => 'nullable|exists:contacts,id',
|
|
'appraisal_id' => 'nullable|exists:aex_appraisals,id',
|
|
'agreed_price' => 'nullable|integer|min:0',
|
|
'commission_percent' => 'nullable|numeric|min:0|max:100',
|
|
'notes' => 'nullable|string',
|
|
]);
|
|
|
|
$listing = Listing::where('business_id', $business->id)->findOrFail($data['listing_id']);
|
|
|
|
try {
|
|
$deal = $this->dealService->createDeal(
|
|
$business,
|
|
$listing,
|
|
$data['deal_type'],
|
|
$data,
|
|
auth()->user()
|
|
);
|
|
} catch (\Throwable $e) {
|
|
return $this->aexUtil->jsonOrRedirect($request, false, $e->getMessage());
|
|
}
|
|
|
|
return $this->aexUtil->jsonOrRedirect(
|
|
$request,
|
|
true,
|
|
__('assetexchange::lang.deal_created'),
|
|
action([self::class, 'show'], [$deal->id])
|
|
);
|
|
}
|
|
|
|
public function show($id)
|
|
{
|
|
$this->authorizeAexAccess('aex.deals.view');
|
|
|
|
$business_id = $this->aexUtil->getBusinessId();
|
|
$deal = Deal::where('business_id', $business_id)
|
|
->with(['listing.seller', 'buyer', 'appraisal', 'offers', 'commissions.user'])
|
|
->findOrFail($id);
|
|
|
|
return view('assetexchange::deals.show', compact('deal'));
|
|
}
|
|
|
|
public function update(Request $request, $id)
|
|
{
|
|
$this->authorizeAexAccess('aex.deals.update');
|
|
|
|
$business = $this->aexUtil->getBusiness();
|
|
$deal = Deal::where('business_id', $business->id)->findOrFail($id);
|
|
|
|
$data = $request->validate([
|
|
'status' => 'sometimes|in:negotiating,quoted,contracted,in_progress,completed,cancelled',
|
|
'agreed_price' => 'nullable|integer|min:0',
|
|
'commission_percent' => 'nullable|numeric|min:0|max:100',
|
|
'buyer_contact_id' => 'nullable|exists:contacts,id',
|
|
'notes' => 'nullable|string',
|
|
]);
|
|
|
|
if (isset($data['status'])) {
|
|
try {
|
|
$deal = $this->dealService->updateStatus($business, $deal, $data['status'], auth()->user());
|
|
} catch (\Throwable $e) {
|
|
return $this->aexUtil->jsonOrRedirect($request, false, $e->getMessage());
|
|
}
|
|
}
|
|
|
|
$fillable = collect($data)->only(['agreed_price', 'commission_percent', 'buyer_contact_id', 'notes'])->toArray();
|
|
if (! empty($fillable)) {
|
|
if (isset($fillable['commission_percent'])) {
|
|
$fillable['commission_amount'] = (int) round(
|
|
($fillable['agreed_price'] ?? $deal->agreed_price) * ($fillable['commission_percent'] / 100)
|
|
);
|
|
}
|
|
$deal->update($fillable);
|
|
$deal = $deal->fresh();
|
|
}
|
|
|
|
return $this->aexUtil->jsonOrRedirect(
|
|
$request,
|
|
true,
|
|
__('assetexchange::lang.deal_updated'),
|
|
action([self::class, 'show'], [$deal->id])
|
|
);
|
|
}
|
|
|
|
public function complete(Request $request, $id)
|
|
{
|
|
$this->authorizeAexAccess('aex.deals.complete');
|
|
|
|
$business = $this->aexUtil->getBusiness();
|
|
$deal = Deal::where('business_id', $business->id)->findOrFail($id);
|
|
|
|
try {
|
|
$deal = $this->dealService->completeDeal($business, $deal, auth()->user());
|
|
} catch (\Throwable $e) {
|
|
return $this->aexUtil->jsonOrRedirect($request, false, $e->getMessage());
|
|
}
|
|
|
|
return $this->aexUtil->jsonOrRedirect(
|
|
$request,
|
|
true,
|
|
__('assetexchange::lang.deal_completed'),
|
|
action([self::class, 'show'], [$deal->id])
|
|
);
|
|
}
|
|
|
|
public function createPo(Request $request, $id)
|
|
{
|
|
$this->authorizeAexAccess('aex.deals.update');
|
|
|
|
$business = $this->aexUtil->getBusiness();
|
|
$deal = Deal::where('business_id', $business->id)->with('listing')->findOrFail($id);
|
|
|
|
try {
|
|
$transaction = $this->erpBridge->createPurchaseOrder(
|
|
$business,
|
|
$deal->listing,
|
|
$deal,
|
|
$request->integer('location_id') ?: null,
|
|
auth()->user()
|
|
);
|
|
} catch (\Throwable $e) {
|
|
return $this->aexUtil->jsonOrRedirect($request, false, $e->getMessage());
|
|
}
|
|
|
|
return $this->aexUtil->jsonOrRedirect(
|
|
$request,
|
|
true,
|
|
__('assetexchange::lang.po_created', ['ref' => $transaction->ref_no ?? $transaction->id]),
|
|
action([self::class, 'show'], [$deal->id])
|
|
);
|
|
}
|
|
|
|
public function createQuotation(Request $request, $id)
|
|
{
|
|
$this->authorizeAexAccess('aex.deals.update');
|
|
|
|
$business = $this->aexUtil->getBusiness();
|
|
$deal = Deal::where('business_id', $business->id)->with('listing')->findOrFail($id);
|
|
|
|
try {
|
|
$transaction = $this->erpBridge->createQuotation(
|
|
$business,
|
|
$deal->listing,
|
|
$deal,
|
|
$request->integer('location_id') ?: null,
|
|
auth()->user()
|
|
);
|
|
} catch (\Throwable $e) {
|
|
return $this->aexUtil->jsonOrRedirect($request, false, $e->getMessage());
|
|
}
|
|
|
|
return $this->aexUtil->jsonOrRedirect(
|
|
$request,
|
|
true,
|
|
__('assetexchange::lang.quotation_created', ['ref' => $transaction->ref_no ?? $transaction->id]),
|
|
action([self::class, 'show'], [$deal->id])
|
|
);
|
|
}
|
|
}
|