98 lines
3.6 KiB
PHP
98 lines
3.6 KiB
PHP
<?php
|
|
namespace App\Services;
|
|
|
|
use App\Repositories\CarRepository;
|
|
use App\Repositories\PurchaseRepository;
|
|
use App\Repositories\SettingRepository;
|
|
use Exception;
|
|
|
|
class PurchaseService {
|
|
protected $carRepo;
|
|
protected $purchaseRepo;
|
|
protected $settingRepo;
|
|
protected $paymentService;
|
|
|
|
public function __construct() {
|
|
$this->carRepo = new CarRepository();
|
|
$this->purchaseRepo = new PurchaseRepository();
|
|
$this->settingRepo = new SettingRepository();
|
|
$this->paymentService = new PaymentService();
|
|
}
|
|
|
|
public function reserveCar($carId, $userId) {
|
|
$this->carRepo->beginTransaction();
|
|
try {
|
|
$car = $this->carRepo->find($carId, true); // Lock for update
|
|
|
|
if (!$car) throw new Exception("Car not found.");
|
|
if ($car['status'] !== 'approved') throw new Exception("Car is not available for sale.");
|
|
if ($car['user_id'] == $userId) throw new Exception("You cannot buy your own car.");
|
|
|
|
// Check if already reserved by someone else and not expired
|
|
if ($car['reserved_by'] && $car['reserved_by'] != $userId && strtotime($car['reservation_expires_at']) > time()) {
|
|
throw new Exception("This car is currently reserved by another buyer.");
|
|
}
|
|
|
|
$this->carRepo->reserve($carId, $userId);
|
|
$this->carRepo->commit();
|
|
return true;
|
|
} catch (Exception $e) {
|
|
$this->carRepo->rollBack();
|
|
throw $e;
|
|
}
|
|
}
|
|
|
|
public function calculateFees($price) {
|
|
$feePercent = $this->settingRepo->get('marketplace_fee_percentage', 5);
|
|
$taxPercent = $this->settingRepo->get('tax_percentage', 10);
|
|
|
|
$fee = ($price * $feePercent) / 100;
|
|
$tax = ($price * $taxPercent) / 100;
|
|
$total = $price + $fee + $tax;
|
|
|
|
return [
|
|
'base_price' => $price,
|
|
'fee' => $fee,
|
|
'tax' => $tax,
|
|
'total' => $total
|
|
];
|
|
}
|
|
|
|
public function initiatePurchase($carId, $userId, $buyerData) {
|
|
$this->purchaseRepo->beginTransaction();
|
|
try {
|
|
$car = $this->carRepo->find($carId, true);
|
|
if (!$car) throw new Exception("Car not found.");
|
|
|
|
$costs = $this->calculateFees($car['price']);
|
|
$transactionId = $this->paymentService->generateUUID();
|
|
$ref = $this->purchaseRepo->generateUniqueReference();
|
|
$token = $this->paymentService->generateVerificationToken($transactionId, $costs['total']);
|
|
|
|
$purchaseId = $this->purchaseRepo->create([
|
|
'transaction_id' => $transactionId,
|
|
'reference_number' => $ref,
|
|
'verification_token' => $token,
|
|
'car_id' => $carId,
|
|
'user_id' => $userId,
|
|
'buyer_name' => $buyerData['name'],
|
|
'buyer_email' => $buyerData['email'],
|
|
'buyer_phone' => $buyerData['phone'],
|
|
'base_price' => $costs['base_price'],
|
|
'marketplace_fee' => $costs['fee'],
|
|
'tax' => $costs['tax'],
|
|
'total_amount' => $costs['total'],
|
|
'status' => 'initiated',
|
|
'escrow_status' => 'awaiting_verification',
|
|
'payment_method' => $buyerData['payment_method'],
|
|
'expires_at' => date('Y-m-d H:i:s', strtotime("+1 hour"))
|
|
]);
|
|
|
|
$this->purchaseRepo->commit();
|
|
return $transactionId;
|
|
} catch (Exception $e) {
|
|
$this->purchaseRepo->rollBack();
|
|
throw $e;
|
|
}
|
|
}
|
|
} |