Edit File: NegotiationOrderService.php
<?php namespace App\Services\User; use App\Enums\NegotiationOrderInvoiceStatusEnum; use App\Enums\NegotiationOrderStatusEnum; use App\Enums\NotificationTypeEnum; use App\Enums\OrderPayStatus; use App\Enums\OrderPayType; use App\Enums\OrderStatusEnum; use App\Enums\ProductDeliveryTypesEnum; use App\Models\Message; use App\Models\NegotiationInvoice; use App\Models\NegotiationOrder; use App\Models\Order; use App\Notifications\OrderNotification; use App\Services\Chat\ChatService; use App\Services\LiveVideo\LiveVideoService; use App\Traits\PaymentServicesTrait; use App\Traits\SettingsTrait; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Notification; class NegotiationOrderService { use SettingsTrait, PaymentServicesTrait; public function __construct(private ChatService $chatService) { $this->model = NegotiationOrder::class; } public function all($paginateNum = 10, $conditions = []): array { $orders = $this->model::with('provider') ->where('status', '!=', NegotiationOrderStatusEnum::Invoice_paid->value) ->where($conditions) ->latest() ->paginate($paginateNum); return ['key' => 'success', 'msg' => __('apis.success'), 'rows' => $orders]; } public function allForDashboard($paginateNum = 15): array { $orders = $this->model::with('provider')->latest()->paginate($paginateNum); return ['key' => 'success', 'msg' => __('apis.success'), 'rows' => $orders]; } public function create($request): array { $min_delivery_price = $this->getKeyFromSetting('min_delivery_price'); $max_delivery_price = $this->getKeyFromSetting('max_delivery_price'); $user = auth()->user(); $provider = $request['provider']; $is_from_home = $request['receiving_method'] == ProductDeliveryTypesEnum::Home->value; $delivery_price = 0; if ($is_from_home) { $delivery_price = getDeliveryPrice( $user->lat, $user->lng, $provider->lat, $provider->lng )['price']; $delivery_price = min(max($delivery_price, $min_delivery_price), $max_delivery_price); } $admin_commission_per_for_delegate = $delivery_price ? $this->getKeyFromSetting('commission_from_delegate') : 0; $data = [ 'neighborhood_id' => $user->neighborhood_to_delivered_id, 'lat' => $is_from_home ? $user->lat : null, 'lng' => $is_from_home ? $user->lng : null, 'map_desc' => $is_from_home ? $user->map_desc : null, 'user_id' => $user->id, 'delivery_price' => $delivery_price, 'admin_commission_per_for_delegate' => $admin_commission_per_for_delegate, 'admin_commission_for_delegate' => $delivery_price * ($admin_commission_per_for_delegate / 100), 'delegate_due_amount' => $delivery_price - $delivery_price * ($admin_commission_per_for_delegate / 100), ]; $order = $this->model::create($request + $data); $room = $this->chatService->createPrivateRoomForNegotiationOrder(creator: $user, type: 'negotiation_order', memberable: $order->provider); $order->update(['room_id' => $room->id]); Notification::send($order->provider, new OrderNotification(order: $order, type: NotificationTypeEnum::Negotiation_Pending->value)); return ['key' => 'success', 'rows' => $order, 'msg' => __('apis.success')]; } public function declineInvoice($order_id, $invoice_id, $msg_id): array { try { $order = $this->model::find(id: $order_id); $invoice = $order->invoices()->find($invoice_id); $status = [ 'value' => NegotiationOrderInvoiceStatusEnum::Invoice_declined->value, 'key' => 'Declined' ]; $this->updateMsg($msg_id, $status); if ($invoice->status == NegotiationInvoice::DECLINED) { return ['key' => 'fail', 'msg' => __('apis.invoice_declined_before')]; } $invoice->update(['status' => NegotiationOrderInvoiceStatusEnum::Invoice_declined->value]); $order->update(['status' => NegotiationOrderStatusEnum::Invoice_declined->value]); Notification::send($order->provider, new OrderNotification(order: $order, type: NotificationTypeEnum::Negotiation_Invoice_declined->value)); return ['key' => 'fail', 'msg' => __('apis.invoice_declined_successfully')]; } catch (\Exception $exception) { return ['key' => 'fail', 'msg' => __('apis.not_found')]; } } public function payInvoice($order_id, $invoice_id, $request): array { try { DB::beginTransaction(); $order = $this->model::find(id: $order_id); $invoice = $order->invoices()->findOrFail($invoice_id); $status = [ 'value' => NegotiationOrderInvoiceStatusEnum::Invoice_paid->value, 'key' => 'Accepted' ]; $this->updateMsg($request->msg_id, $status); $payResult = match ((int)$request->pay_type) { OrderPayType::WALLET->value => $this->payWithWallet(user: auth()->user(), order: $invoice), OrderPayType::CASH->value => $this->payWithCash(order: $invoice), OrderPayType::ONLINE->value => $this->payWithOnline(order: $invoice, request: $request), OrderPayType::APPLE_PAY->value => $this->payWithApplePay(order: $invoice, request: $request), }; if ($payResult['key'] == 'success') { $order->update(['status' => NegotiationOrderStatusEnum::Invoice_paid->value]); $invoice->update(['status' => NegotiationOrderInvoiceStatusEnum::Invoice_paid->value]); $data = $this->prepareDataForOrder($invoice); $normalOrder = Order::create($data); $normalOrder->orderItems()->create($this->prepareDataForOrderItem($invoice, $normalOrder->id)); $invoice->order->negotiationRoom->update(['order_id' => $normalOrder->id]); } Notification::send($order->provider, new OrderNotification(order: $order, type: NotificationTypeEnum::Negotiation_Invoice_paid->value)); DB::commit(); return ['key' => $payResult['key'], 'msg' => $payResult['msg'], 'data' => $payResult['data']]; } catch (\Exception $exception) { DB::rollBack(); return ['key' => 'fail', 'msg' => $exception->getMessage(), 'data' => []]; } } protected function updateMsg($msg_id, $status) { $msg = Message::find($msg_id); $body = json_decode($msg->body, true); $body['status'] = $status; $msg->update(['body' => json_encode($body, JSON_UNESCAPED_UNICODE)]); return true; } public function createInvoice($order_id, $request): array { try { DB::beginTransaction(); $order = $this->find(id: $order_id)['row']; $data = $this->prepareDataForInvoice($order, $request); $invoice = $order->invoices()->create($data); if ($invoice) { $data['delivery_price'] = $order->delivery_price; $data['id'] = $invoice->id; } $this->chatService->storeMessage(room: $order->negotiationRoom, sender: auth()->user(), message: json_encode($data, JSON_UNESCAPED_UNICODE)); Notification::send($order->user, new OrderNotification(order: $order, type: NotificationTypeEnum::Negotiation_Invoice_generated->value)); DB::commit(); return ['key' => 'success', 'rows' => $order, 'msg' => __('apis.success')]; } catch (\Exception $exception) { DB::rollBack(); return ['key' => 'fail', 'rows' => [], 'msg' => $exception->getMessage()]; } } public function prepareDataForInvoice($order, $request): array { $vat_ratio = $this->getKeyFromSetting('vat_ratio') ?? 0; $vat_amount = $request->order_total * ($vat_ratio / 100); $admin_commission_per = $this->getKeyFromSetting('commission_from_provider') ?? 0; $admin_commission_amount = $request->order_total * ($admin_commission_per / 100); return [ 'user_id' => $order->user?->id, 'provider_id' => auth()->id(), 'total' => $request->order_total, 'vat_per' => $vat_ratio, 'vat_amount' => $vat_amount, 'admin_commission_per' => $admin_commission_per, // from provider 'admin_commission' => $admin_commission_amount, // from provider 'final_total' => $request->order_total + $vat_amount + $order->delivery_price, ]; } public function find($id): array { try { $order = $this->model::with('latestInvoice')->findOrFail($id); return ['key' => 'success', 'row' => $order, 'msg' => __('apis.success')]; } catch (\Exception $exception) { // return ['key' => 'fail', 'msg' => __('apis.not_found')]; return ['key' => 'fail', 'msg' => $exception->getMessage(), 'row' => collect([])]; } } private function prepareDataForOrder($invoice): array { $order = $invoice->order; return [ 'user_id' => auth()->id(), 'lat' => $order->lat ?? null, 'lng' => $order->lng ?? null, 'provider_id' => $order->provider_id, 'map_desc' => $order->map_desc ?? null, 'city_id' => $order->city_id ?? null, 'neighborhood_id' => $order->neighborhood_id ?? null, 'total_products' => $invoice->total, 'vat_per' => $invoice->vat_per, 'vat_amount' => $invoice->vat_amount, 'receiving_method' => $order->receiving_method, 'delivery_price' => $order->delivery_price ?? 0, 'final_total' => $invoice->final_total, 'pay_type' => $invoice->pay_type, 'pay_status' => $invoice->pay_status, 'status' => OrderStatusEnum::Accepted->value, 'schedule_execution_date' => $order->schedule_execution_date, 'schedule_execution_time' => $order->schedule_execution_time, 'commission_ratio_from_provider' => $invoice->admin_commission_per, 'commission_value_from_provider' => $invoice->admin_commission, 'provider_due_amount' => $invoice->total + $invoice->vat_amount - $invoice->admin_commission, 'commission_value_from_delegate' => $order->admin_commission_for_delegate, 'commission_ratio_from_delegate' => $order->admin_commission_per_for_delegate, 'admin_commission_value' => $order->admin_commission_for_delegate + $invoice->admin_commission, 'room_id' => $order->room_id, 'notes' => $order->notes, 'car_color' => $order->car_color, 'car_model' => $order->car_model, 'car_plat_number' => $order->car_plat_number, 'receiving_in_store_notes' => $order->receiving_in_store_notes, ]; } private function prepareDataForOrderItem($invoice, $orderId): array { return [ 'order_id' => $orderId, 'product_id' => $invoice->order->product_id, 'quantity' => $invoice->order->quantity, 'unit_price' => $invoice->total, 'total' => $invoice->total, ]; } public function displayOrderByOrderNumber($order_num, $conditions = []) { return NegotiationOrder::with([ 'invoices' => function ($query) { $query->where('pay_status', OrderPayStatus::PAID->value)->first(); } ])->where('order_num', $order_num) ->when(!empty($conditions), fn($q) => $q->where($conditions))->first(); } public function negotiationOrdersCount($conditions = []) { return NegotiationOrder::where($conditions)->count(); } }
Back to File Manager