diff --git a/app/Classes/General/Eloquent/Filters/CreatedAfterOrEqual.php b/app/Classes/General/Eloquent/Filters/CreatedAfterOrEqual.php new file mode 100644 index 00000000..9df98f40 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/CreatedAfterOrEqual.php @@ -0,0 +1,23 @@ +getModel()->getTable(); + $startDate = Carbon::createFromFormat('d-m-Y', $value)->startOfDay(); + return $builder->where("{$table}.created_at", '>=', $startDate); + } +} \ No newline at end of file diff --git a/app/Classes/General/Eloquent/Filters/CreatedBeforeOrEqual.php b/app/Classes/General/Eloquent/Filters/CreatedBeforeOrEqual.php new file mode 100644 index 00000000..5b349540 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/CreatedBeforeOrEqual.php @@ -0,0 +1,22 @@ +getModel()->getTable(); + $endDate = Carbon::createFromFormat('d-m-Y', $value)->endOfDay(); + return $builder->where("{$table}.created_at", '<=', $endDate); + } +} diff --git a/app/Classes/General/Eloquent/Filters/OwnerId.php b/app/Classes/General/Eloquent/Filters/OwnerId.php index eac7e32d..c2dfa685 100644 --- a/app/Classes/General/Eloquent/Filters/OwnerId.php +++ b/app/Classes/General/Eloquent/Filters/OwnerId.php @@ -14,7 +14,8 @@ class OwnerId implements Filter */ public static function apply(Builder $builder, $value) { - return $builder->where('owner_id', $value); + $table = $builder->getModel()->getTable(); + return $builder->where("{$table}.owner_id", $value); } } \ No newline at end of file diff --git a/app/Classes/General/Eloquent/Filters/OwnerType.php b/app/Classes/General/Eloquent/Filters/OwnerType.php new file mode 100644 index 00000000..3feedccd --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/OwnerType.php @@ -0,0 +1,21 @@ +getModel()->getTable(); + return $builder->where("{$table}.owner_type", $value); + } + +} \ No newline at end of file diff --git a/app/Classes/General/Eloquent/Filters/StatusIn.php b/app/Classes/General/Eloquent/Filters/StatusIn.php index cbfdfbd0..85425802 100644 --- a/app/Classes/General/Eloquent/Filters/StatusIn.php +++ b/app/Classes/General/Eloquent/Filters/StatusIn.php @@ -14,7 +14,8 @@ class StatusIn implements Filter */ public static function apply(Builder $builder, $value) { - return $builder->whereIn('status', $value); + $table = $builder->getModel()->getTable(); + return $builder->whereIn("{$table}.status", $value); } } \ No newline at end of file diff --git a/app/Classes/General/Eloquent/Filters/WithOrderReferenceLike.php b/app/Classes/General/Eloquent/Filters/WithOrderReferenceLike.php new file mode 100644 index 00000000..acc9f161 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/WithOrderReferenceLike.php @@ -0,0 +1,27 @@ +join('transactions as t2', 't2.payment_reference', '=', 'transactions.bill_no') + ->join('transactions as t3', 't3.id', '=', 't2.owner_id') + ->join('packing_lists', 'packing_lists.id', '=', 't3.owner_id') + ->join('orders', function ($join) use ($value) { + $join->on('orders.id', '=', 'packing_lists.owner_id') + ->where('orders.reference', 'LIKE', '%'.$value.'%'); + }) + ->addSelect(['transactions.*', 't2.id as paymentTransactionId', 't3.id as invoiceTransactionId', 'packing_lists.id as packingListId', 'orders.reference as orderReference']); + } +} \ No newline at end of file diff --git a/app/Classes/Modules/Exports/Services/ExportsCustomersWalletTransactionHistory.php b/app/Classes/Modules/Exports/Services/ExportsCustomersWalletTransactionHistory.php new file mode 100644 index 00000000..69571b1f --- /dev/null +++ b/app/Classes/Modules/Exports/Services/ExportsCustomersWalletTransactionHistory.php @@ -0,0 +1,108 @@ +request = $request; + } + + public function headings(): array + { + return [ + 'Date', + 'Description', + 'Incoming', + 'Outgoing', + 'Balance', + ]; + } + + /** + * @return \Illuminate\Support\Collection|mixed + */ + public function query() + { + $wallet = Wallet::find($this->request->route('wallet_id')); + $transactions = $wallet->transactions()->whereIn('transactions.status', [2, 3])->orderBy('id'); + + return $transactions; + } + + /** + * @param Transaction $transaction + * + * @return array + */ + public function map($transaction): array + { + $decimals = $this->request->route('is_precise') == 'true' ? 5 : 2; + + $description = ''; + switch ((int) $transaction->type) { + case TransactionType::TOP_UP: + $description = (float) $transaction->amount . ' Credit Top up'; + break; + case TransactionType::GROUP_PAYMENT: + $description = (float) $transaction->amount . ' Credit Top up'; + break; + case TransactionType::CREDIT_NOTE: + $description = 'Credit Voucher for ' . $transaction->payment_reference; + break; + case TransactionType::PAYMENT: + $booking = Transaction::where('payment_reference', $transaction->bill_no)->first()->owner; + + if (!$booking) { + $description = 'Payment for unknown booking, please contact tech support.'; + break; + } + + $marking = $booking->marking; + $description = 'Payment For booking refs' . $marking; + break; + case TransactionType::DEBIT_NOTE: + $description = 'Debit Voucher for ' . $transaction->payment_reference; + break; + } + + $incoming = $outgoing = ''; + + if (in_array($transaction->type, [TransactionType::TOP_UP, TransactionType::CREDIT_NOTE, TransactionType::GROUP_PAYMENT])) { + $incoming = number_format($transaction->amount, $decimals, '.', ','); + $this->runningBalance += $transaction->amount; + } + + if (in_array($transaction->type, [TransactionType::PAYMENT, TransactionType::DEBIT_NOTE])) { + $outgoing = number_format($transaction->amount, $decimals, '.', ','); + $this->runningBalance -= $transaction->amount; + } + + return [ + Carbon::parse($transaction->created_at)->format('d-m-Y h:i:s A'), + $description, + $incoming, + $outgoing, + number_format($this->runningBalance, $decimals, '.', ',') + ]; + } +} diff --git a/app/Classes/Modules/Transactions/ControllersLogic/ListWalletTransactionsLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/ListWalletTransactionsLogic.php new file mode 100644 index 00000000..af51b2e9 --- /dev/null +++ b/app/Classes/Modules/Transactions/ControllersLogic/ListWalletTransactionsLogic.php @@ -0,0 +1,79 @@ +listsTransactions = $listsTransactions; + } + + /** + * @return array + */ + protected function notification():array { + return [ + 'title' => 'Retrieved Wallet Transactions', + 'message' => 'You have successfully retrieved a list of transactions' + ]; + } + + /** @var ListsTransactions */ + private $listsTransactions; + + public function logic(Request $request) : JsonResponse + { + $query = $this->listsTransactions->execute($this->listsTransactions->deserializeFilters($request->input('filters'))); + + if (str_contains($request->input('filters'), "owner_id") && $query->count() > 0) { + $wallet_total_incoming = Transaction::where('owner_type', $query->first()->owner_type) + ->where('owner_id', $query->first()->owner_id) + ->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]) + ->whereIn('type', [TransactionType::TOP_UP, TransactionType::CREDIT_NOTE, TransactionType::GROUP_PAYMENT]) + ->sum('amount'); + + $wallet_total_outgoing = Transaction::where('owner_type', $query->first()->owner_type) + ->where('owner_id', $query->first()->owner_id) + ->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]) + ->whereIn('type', [TransactionType::PAYMENT, TransactionType::DEBIT_NOTE]) + ->sum('amount'); + + $currentWalletBalance = $wallet_total_incoming - $wallet_total_outgoing; + $incoming = Transaction::where('owner_type', $query->first()->owner_type) + ->where('owner_id', $query->first()->owner_id) + ->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]) + ->whereIn('type', [TransactionType::TOP_UP, TransactionType::CREDIT_NOTE, TransactionType::GROUP_PAYMENT]) + ->where('id', '>', $query->first()->id) + ->sum('amount'); + $outgoing = Transaction::where('owner_type', $query->first()->owner_type) + ->where('owner_id', $query->first()->owner_id) + ->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]) + ->whereIn('type', [TransactionType::PAYMENT, TransactionType::DEBIT_NOTE]) + ->where('id', '>', $query->first()->id) + ->sum('amount'); + $runningBalanceInReverse = $currentWalletBalance - $incoming + $outgoing; + $request['running_balance'] = $runningBalanceInReverse; + } + + return $this->collectionResponse(WalletTransactionResource::collection($query)); + + } + + + +} diff --git a/app/Http/Controllers/Exports/ExportCustomersWalletTransactionToExcelController.php b/app/Http/Controllers/Exports/ExportCustomersWalletTransactionToExcelController.php new file mode 100644 index 00000000..742c4be1 --- /dev/null +++ b/app/Http/Controllers/Exports/ExportCustomersWalletTransactionToExcelController.php @@ -0,0 +1,36 @@ +headers->set('Authorization', 'Bearer ' . $token); + } + + public function export(Request $request) + { + $exportsTransactions = new ExportsCustomersWalletTransactionHistory($request); + $wallet = Wallet::find($request->route('wallet_id')); + $company_marking = $wallet->owner->connections->first()->invitee_reference; + + $filename = $company_marking . '-wallet-' . ($request->route('is_precise') == 'true' ? 'precise-' : '') . 'transaction-history.xls'; + $response = $exportsTransactions->download($filename, Excel::XLS, ['Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']); + ob_end_clean(); + return $response; + } +} diff --git a/app/Http/Controllers/Transactions/ListWalletTransactionsController.php b/app/Http/Controllers/Transactions/ListWalletTransactionsController.php new file mode 100644 index 00000000..e83d7b58 --- /dev/null +++ b/app/Http/Controllers/Transactions/ListWalletTransactionsController.php @@ -0,0 +1,21 @@ +execute($request); + } +} diff --git a/app/Http/Resources/WalletTransactionResource.php b/app/Http/Resources/WalletTransactionResource.php index b668c053..2550a061 100644 --- a/app/Http/Resources/WalletTransactionResource.php +++ b/app/Http/Resources/WalletTransactionResource.php @@ -20,12 +20,15 @@ class WalletTransactionResource extends JsonResource public function toArray($request) { $description = ''; + $current_running_balance = $request['running_balance']; switch((int) $this->type){ case TransactionType::TOP_UP: $description = (double) $this->amount.' Credit Top up'; + $request['running_balance'] = bcsub($request['running_balance'], $this->amount, 5); break; case TransactionType::CREDIT_NOTE: $description = 'Credit Voucher for '.$this->payment_reference; + $request['running_balance'] = bcsub($request['running_balance'], $this->amount, 5); break; case TransactionType::PAYMENT: $invoice = Transaction::where('payment_reference', $this->bill_no)->first(); @@ -40,13 +43,16 @@ class WalletTransactionResource extends JsonResource break; } + $request['running_balance'] = bcadd($request['running_balance'], $this->amount, 5); $marking = $order->reference; $description = 'Payment For order refs.'.''.$marking.''; break; case 11: + $request['running_balance'] = bcadd($request['running_balance'], $this->amount, 5); $description = 'Debit Voucher for '.$this->payment_reference; break; case 15: + $request['running_balance'] = bcsub($request['running_balance'], $this->amount, 5); $description = (double) $this->amount.' Credit Top up'; break; @@ -61,6 +67,7 @@ class WalletTransactionResource extends JsonResource 'payment_method' => (float) $this->payment_method, // 'issuer_name' => $this->issuerCompany->name, 'amount' => (double) $this->amount, + 'running_balance' => (double) $current_running_balance, 'service_charge' => (double) $this->service_charge, 'tax' => (double) $this->tax, 'status' => (int) $this->status, diff --git a/resources/assets/vue/components/wallets/elements/CustomerTransactionSectionComponent.vue b/resources/assets/vue/components/wallets/elements/CustomerTransactionSectionComponent.vue index d60032e0..7ad12009 100644 --- a/resources/assets/vue/components/wallets/elements/CustomerTransactionSectionComponent.vue +++ b/resources/assets/vue/components/wallets/elements/CustomerTransactionSectionComponent.vue @@ -9,6 +9,43 @@