Edit File: FinancialTransactionsService.php
<?php namespace App\Services\Api; use App\Enums\OrderPayType; use App\Enums\OrderStatusEnum; use App\Enums\ProductDeliveryTypesEnum; use App\Enums\SettlementType; use App\Models\{Order, Settlement, SettlementItem}; use App\Services\{BaseService}; use App\Services\Payment\PayProcess; use App\Traits\{CartOrderTrait, LogException, PaymentServicesTrait, SettingsTrait}; use Illuminate\Support\Facades\DB; class FinancialTransactionsService extends BaseService { use CartOrderTrait, SettingsTrait, LogException, PaymentServicesTrait; public function __construct() { parent::__construct(Order::class); } public function settlementRequest() { $providerOrDelegate = auth()->user(); $orders = $this->getDueOrders($providerOrDelegate); if (Settlement::where([ 'transactionable_id' => $providerOrDelegate->id, 'transactionable_type' => get_class($providerOrDelegate) ])->where('status', 'pending')->exists()) { return [ 'key' => 'fail', 'msg' => trans('site.exist_settlement') ]; } // get transactions for provider and delegate also check if has indebtedness for delegate $creditAuthTransactionsQuery = $this->getCreditAuthTransactionsQuery(); $debitAuthTransactionsQuery = $this->getDebitAuthTransactionsQuery(); $creditAuthTransactions = $creditAuthTransactionsQuery->sum('amount'); $debitAuthTransactions = $debitAuthTransactionsQuery->sum('amount'); if ($debitAuthTransactions > $creditAuthTransactions) { return ['key' => 'fail', 'msg' => __('apis.should_pay_indebtedness')]; } try { DB::beginTransaction(); $orders = $orders->get(); $settlementItems = []; //Loop Over Orders To Create Request if ($orders->count() > 0) { $settlementAmount = $creditAuthTransactions - $debitAuthTransactions; // //Create Settlement Request $settlement = $providerOrDelegate->settlements()->create([ 'amount' => $settlementAmount, 'indebtedness' => $debitAuthTransactions, 'type' => SettlementType::DUES->value, ]); foreach ($orders as $order) { $settlementItems[] = [ 'settlement_id' => $settlement->id, 'order_id' => $order->id, 'created_at' => now(), ]; } } else { return [ 'key' => 'fail', 'msg' => __('apis.settlements.no_orders_to_settlement') ]; } SettlementItem::insert($settlementItems); // update order transactions to be with status pending if ($creditAuthTransactionsQuery->exists()) { $creditAuthTransactionsQuery->update(['status' => 'pending']); } if ($debitAuthTransactionsQuery->exists()) { $debitAuthTransactionsQuery->update(['status' => 'pending']); } // Notification::send(Admin::first(), new NewOrderSettlementNotification($settlement)); DB::commit(); return [ 'key' => 'success', 'msg' => __('apis.settlements.settlements_request_added') ]; } catch (\Exception $e) { DB::rollBack(); $this->logMethodException($e); return ['key' => 'fail', 'msg' => $e->getMessage()]; } } public function currrentDueOrders() { $providerOrDelegate = auth()->user(); $orders = $this->getDueOrders($providerOrDelegate); // get transactions for provider and delegate also check if has indebtedness for delegate $creditAuthTransactions = $this->getCreditAuthTransactionsQuery()->sum('amount'); $debitAuthTransactions = $this->getDebitAuthTransactionsQuery()->sum('amount'); $total = $orders?->sum('total_products'); $adminCommisionValue = auth('provider')->user() ? $orders?->sum('commission_value_from_provider') : $orders?->sum('commission_value_from_delegate'); $vatAmount = $orders?->sum('vat_amount'); $totalDueAmount = $creditAuthTransactions - $debitAuthTransactions; $deliveryPriceAmount = $orders?->sum('delivery_price'); $final_total = $orders?->sum('final_total'); $debts = $debitAuthTransactions > $creditAuthTransactions ? $debitAuthTransactions - $creditAuthTransactions : $debitAuthTransactions; $statistics = [ 'total' => number_format($total, 2), 'total_due_amount' => number_format($totalDueAmount, 2), 'admin_commission_value' => number_format($adminCommisionValue, 2), 'delivery_price' => number_format($deliveryPriceAmount, 2), 'vat_amount' => number_format($vatAmount, 2), 'final_total' => number_format($final_total, 2), 'indebtedness' => number_format($debts, 2), 'is_indebtedness_greater_than_credit' => $debts > $totalDueAmount ]; return [ 'key' => 'success', 'msg' => __('apis.success'), 'statistics' => $statistics, 'orders' => $orders->paginate(15), ]; } public function getSettlementOrdersAccordingToStatus(array $statuses, array $with = []) { $user = auth()->user(); return Settlement::with($with)->where([ ['transactionable_type', get_class($user)], ['transactionable_id', $user->id] ])->whereIn('status', $statuses)->latest()->paginate(15); } public function showSettlment($id) { $user = auth()->user(); return Settlement::with('settlementItems')->where([ ['id', $id], ['transactionable_type', get_class($user)], ['transactionable_id', $user->id], ])->firstOrFail(); } public function createOrderTransaction($request) { $isOrderByDelivery = $request['order']['receiving_method']['value'] == ProductDeliveryTypesEnum::Home->value; $order = $request['order']; $order->orderTransactions()->create([ 'provider_id' => $order['provider_id'], 'type' => 'credit', 'amount' => $order['provider_due_amount'], ]); if ($isOrderByDelivery) { $isOrderPayWithCash = $order['pay_type'] == OrderPayType::CASH->value; $order->orderTransactions()->create([ 'delegate_id' => $order['delegate_id'], 'type' => !$isOrderPayWithCash ? 'credit' : 'debit', 'amount' => !$isOrderPayWithCash ? $order['delegate_due_amount'] : $order['final_total'] - $order['delegate_due_amount'], ]); } } // Very Important Notes // /* For Delegates :: What Delegate should pay to admin ? - if user has credit and debits, we substruct the debits from the credits and pay the remaining amount to admin - if he has no credits, we pay the debits to admin */ public function payIndebtedness($provider) { // get transactions for provider and delegate also check if has indebtedness for delegate $creditAuthTransactionsQuery = $this->getCreditAuthTransactionsQuery(); $debitAuthTransactionsQuery = $this->getDebitAuthTransactionsQuery(); $creditAuthTransactions = $creditAuthTransactionsQuery->sum('amount'); $debitAuthTransactions = $debitAuthTransactionsQuery->sum('amount'); if ($debitAuthTransactions == 0) { return ['key' => 'fail', 'msg' => __('apis.no_debts')]; } $whatUserShouldPay = $debitAuthTransactions > $creditAuthTransactions ? $debitAuthTransactions - $creditAuthTransactions : $debitAuthTransactions; // TODO :: update when pay installion || will pay with online DB::beginTransaction(); try { //get orders $orders = $this->getDueOrders($provider); $settlement = $provider->settlements()->create([ 'status' => 'accepted', 'amount' => 0, 'indebtedness' => $whatUserShouldPay, 'type' => SettlementType::INDEBTEDNESS->value, ]); // TODO :: update when pay installion || will pay with wallet (new PayProcess())->payAmountToAdmin($debitAuthTransactions); $orders = $orders->get(); $settlementItems = []; //Loop Over Orders To Create Request if ($orders->count() > 0) { foreach ($orders as $order) { $settlementItems[] = [ 'settlement_id' => $settlement->id, 'order_id' => $order->id, 'created_at' => now(), ]; } } SettlementItem::insert($settlementItems); // update order transactions to be with status pending if ($creditAuthTransactionsQuery->exists()) { $creditAuthTransactionsQuery->update(['status' => 'accepted']); } if ($debitAuthTransactionsQuery->exists()) { $debitAuthTransactionsQuery->update(['status' => 'accepted']); } DB::commit(); return ['key' => 'success', 'msg' => __('apis.settlements.debts_pay_done_successfully')]; } catch (\Exception $e) { DB::rollBack(); $this->logMethodException($e); return ['key' => 'fail', 'msg' => $e->getMessage()]; } } private function getDueOrders($user) { $relationId = strtolower(class_basename($user)) . '_id'; return Order::query() ->where('status', OrderStatusEnum::Client_delivered->value) ->where($relationId, $user->id) ->where('pay_status', true) ->whereHas('orderTransactions', function ($query) use ($user, $relationId) { $query->where($relationId, $user->id) ->where('status', 'new'); })->latest(); } private function getCreditAuthTransactionsQuery() { return auth()->user()->orderTransactions() ->whereHas('order', function ($query) { $query->where('status', OrderStatusEnum::Client_delivered->value); })->where([['type', 'credit'], ['status', 'new']]); } private function getDebitAuthTransactionsQuery() { return auth()->user()->orderTransactions()->whereHas('order', function ($query) { $query->where('status', OrderStatusEnum::Client_delivered->value); })->where([['type', 'debit'], ['status', 'new']]); } }
Back to File Manager