This commit is contained in:
glovetleong
2022-04-06 22:54:01 +08:00
6 changed files with 195 additions and 156 deletions
@@ -23,6 +23,8 @@ class PendingPurchaseOrder implements Filter
});
})->whereDoesntHave('transactions', function($transaction){
return $transaction->where('type', TransactionType::PURCHASE_ORDER)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]);
})->whereHas('transactions', function($transaction){
return $transaction->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]);
});
}
@@ -24,71 +24,48 @@ use Carbon\Carbon;
class CreateCashBackTransactionProcessor
{
/** @var UpdatesTransactionStatus */
private $updatesTransactionStatus;
/** @var CreatesTransaction */
private $createsTransaction;
/** @var CreatesTransactionDetail */
private $createsTransactionDetail;
/** @var UpdatesTransaction */
private $updatesTransaction;
/** @var DeletesTransactionDetails */
private $deletesTransactionDetails;
/** @var GeneratesTransactionBillNumber */
private $generatesTransactionBillNumber;
/** @var CreatesWallet */
private $createsWallet;
/** @var GeneratesWalletCode */
private $generatesWalletCode;
/** @var CreditWalletProcessor */
private $creditWalletProcessor;
/**
* CreateCashBackTransactionProcessor constructor.
* @param UpdatesTransactionStatus $updatesTransactionStatus
* @param CreatesTransaction $createsTransaction
* @param CreatesTransactionDetail $createsTransactionDetail
* @param UpdatesTransaction $updatesTransaction
* @param DeletesTransactionDetails $deletesTransactionDetails
* @param GeneratesTransactionBillNumber $generatesTransactionBillNumber
* @param CreditWalletProcessor $creditWalletProcessor
*/
public function __construct(UpdatesTransactionStatus $updatesTransactionStatus, CreatesTransaction $createsTransaction, CreatesTransactionDetail $createsTransactionDetail, UpdatesTransaction $updatesTransaction, DeletesTransactionDetails $deletesTransactionDetails, GeneratesTransactionBillNumber $generatesTransactionBillNumber, GeneratesWalletCode $generatesWalletCode, CreditWalletProcessor $creditWalletProcessor)
public function __construct(CreatesTransaction $createsTransaction, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreditWalletProcessor $creditWalletProcessor)
{
$this->createsTransaction = $createsTransaction;
$this->createsTransactionDetail = $createsTransactionDetail;
$this->updatesTransaction = $updatesTransaction;
$this->deletesTransactionDetails = $deletesTransactionDetails;
$this->generatesTransactionBillNumber = $generatesTransactionBillNumber;
$this->generatesWalletCode = $generatesWalletCode;
$this->creditWalletProcessor = $creditWalletProcessor;
}
/**
* @param Booking $booking
* @param TransactionObject $object
* @param Transaction $transaction
* @return Transaction|\Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(Transaction $transaction)
{
// leave this disabled until ready to launch to production
return;
// ((MYR) * (cash back %)) * (1/conversion rate)
$current_total_cash_back = Transaction::
where('type', TransactionType::CASH_BACK)
->whereMonth('created_at', Carbon::now()->month)->sum('amount');
if (
$current_total_cash_back < CashBack::MAX &&
$transaction->owner()->first()->transactions()->where('type', TransactionType::PURCHASE_ORDER)->count() > 0
$transaction->owner()->first()->transactions()->where('type', TransactionType::PURCHASE_ORDER)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED])->count() > 0
) {
$cash_back_segemnt = CashBack::SEGMENT;
@@ -0,0 +1,29 @@
<?php
namespace App\Http\Controllers\Wallets;
use App\Classes\ValueObjects\Response\ApiResponseObject;
use App\Classes\ValueObjects\Constants\HttpStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Transaction;
use App\Models\Wallet;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class WalletReportController
{
public function walletsReport(Request $request): JsonResponse
{
return (new ApiResponseObject(
'fetch service report Successful',
'',
HttpStatus::OK_WITH_MESSAGE,
['data' => [
'walletSum' => (float) Wallet::all()->sum('amount'),
'outgoingSum' => (float) Transaction::where('type', TransactionType::PAYMENT)->where('owner_type', Wallet::class)->sum('amount'),
'incomingSum' => (float) Transaction::whereIn('type', [TransactionType::TOP_UP, TransactionType::CREDIT_NOTE])->where('owner_type', Wallet::class)->sum('amount'),
]]
))->handler();
}
}
@@ -26,7 +26,7 @@
</div>
<div class="col">
<div class="font-heading fs-10">{{item.holder_name}}</div>
<div class="font-heading fs-11 text-complete m-b-5">{{item.bank.type === 3 ? item.bank.account_no : item.bank.account_no.replace(/[^\dA-Z]/g, '').replace(/(.{4})/g, '$1 ').trim() }}</div>
<div class="font-heading fs-11 text-complete m-b-5">{{item.type === 3 ? item.account_no : item.account_no.replace(/[^\dA-Z]/g, '').replace(/(.{4})/g, '$1 ').trim() }}</div>
</div>
<div class="col-auto">
<div class="row align-items-center">
@@ -1,122 +1,127 @@
<template>
<div class="row">
<div class="col">
<div class="row">
<div class="col-12 p-0" style="width: 500px; height:350px">
<canvas id="wallets-chart"></canvas>
</div>
</div>
<div class="row">
<loading-component v-if="isLoading"></loading-component>
<div class="row" v-if="!isLoading">
<div class="col">
<div class="card no-border bg-success text-white widget-loader-bar m-b-10">
<div class="container-xs-height full-height">
<div class="row-xs-height">
<div class="col-xs-height col-top">
<div class="card-header top-left top-right">
<div class="card-title">
<span class="font-montserrat fs-11 all-caps">Total Amount</span>
<div class="row">
<div class="col-12 p-0" style="height:350px">
<canvas id="wallets-chart" class="w-100"></canvas>
</div>
</div>
<div class="row">
<div class="col">
<div class="card no-border bg-success text-white widget-loader-bar m-b-10">
<div class="container-xs-height full-height">
<div class="row-xs-height">
<div class="col-xs-height col-top">
<div class="card-header top-left top-right">
<div class="card-title">
<span class="font-montserrat fs-11 all-caps">Total Amount</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row-xs-height">
<div class="col-xs-height col-top">
<div class="p-l-20 p-t-50 p-b-40 p-r-20">
<h3 class="no-margin p-b-5 text-white">MYR 500,123</h3>
<div class="row-xs-height">
<div class="col-xs-height col-top">
<div class="p-l-20 p-t-50 p-b-40 p-r-20">
<h3 class="no-margin p-b-5 text-white">MYR {{(Math.round((report.walletSum + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}</h3>
</div>
</div>
</div>
</div>
</div>
<div class="row-xs-height">
<div class="col-xs-height col-bottom">
<div class="progress progress-small m-b-0">
<div class="progress-bar progress-bar-success" style="width: 0"></div>
<div class="row-xs-height">
<div class="col-xs-height col-bottom">
<div class="progress progress-small m-b-0">
<div class="progress-bar progress-bar-success" style="width: 0"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col">
<div class="card no-border bg-success-light text-white widget-loader-bar m-b-10">
<div class="container-xs-height full-height">
<div class="row-xs-height">
<div class="col-xs-height col-top">
<div class="card-header top-left top-right">
<div class="card-title">
<span class="font-montserrat fs-11 all-caps">Total Incoming Amount</span>
<div class="col">
<div class="card no-border bg-success-light text-white widget-loader-bar m-b-10">
<div class="container-xs-height full-height">
<div class="row-xs-height">
<div class="col-xs-height col-top">
<div class="card-header top-left top-right">
<div class="card-title">
<span class="font-montserrat fs-11 all-caps">Total Incoming Amount</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row-xs-height">
<div class="col-xs-height col-top">
<div class="p-l-20 p-t-50 p-b-40 p-r-20">
<h3 class="no-margin p-b-5 text-white">MYR 500,123</h3>
<div class="row-xs-height">
<div class="col-xs-height col-top">
<div class="p-l-20 p-t-50 p-b-40 p-r-20">
<h3 class="no-margin p-b-5 text-white">MYR {{(Math.round((report.incomingSum + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}</h3>
</div>
</div>
</div>
</div>
</div>
<div class="row-xs-height">
<div class="col-xs-height col-bottom">
<div class="progress progress-small m-b-0">
<div class="progress-bar progress-bar-success" style="width: 0"></div>
<div class="row-xs-height">
<div class="col-xs-height col-bottom">
<div class="progress progress-small m-b-0">
<div class="progress-bar progress-bar-success" style="width: 0"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col">
<div class="card no-border bg-warning widget-loader-bar m-b-10">
<div class="container-xs-height full-height">
<div class="row-xs-height">
<div class="col-xs-height col-top">
<div class="card-header top-left top-right">
<div class="card-title">
<span class="font-montserrat fs-11 all-caps">Total Outgoing Amount</span>
<div class="col">
<div class="card no-border bg-warning widget-loader-bar m-b-10">
<div class="container-xs-height full-height">
<div class="row-xs-height">
<div class="col-xs-height col-top">
<div class="card-header top-left top-right">
<div class="card-title">
<span class="font-montserrat fs-11 all-caps">Total Outgoing Amount</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row-xs-height">
<div class="col-xs-height col-top">
<div class="p-l-20 p-t-50 p-b-40 p-r-20">
<h3 class="no-margin p-b-5">MYR 500,123</h3>
<div class="row-xs-height">
<div class="col-xs-height col-top">
<div class="p-l-20 p-t-50 p-b-40 p-r-20">
<h3 class="no-margin p-b-5 text-white">MYR {{(Math.round((report.outgoingSum + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}</h3>
</div>
</div>
</div>
</div>
</div>
<div class="row-xs-height">
<div class="col-xs-height col-bottom">
<div class="progress progress-small m-b-0">
<div class="progress-bar progress-bar-primary" style="width: 0"></div>
<div class="row-xs-height">
<div class="col-xs-height col-bottom">
<div class="progress progress-small m-b-0">
<div class="progress-bar progress-bar-primary" style="width: 0"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col">
<div class="card no-border bg-danger text-white widget-loader-bar m-b-10">
<div class="container-xs-height full-height">
<div class="row-xs-height">
<div class="col-xs-height col-top">
<div class="card-header top-left top-right">
<div class="card-title">
<span class="font-montserrat fs-11 all-caps">Total Floating Amount</span>
<div class="col d-none">
<div class="card no-border bg-danger text-white widget-loader-bar m-b-10">
<div class="container-xs-height full-height">
<div class="row-xs-height">
<div class="col-xs-height col-top">
<div class="card-header top-left top-right">
<div class="card-title">
<span class="font-montserrat fs-11 all-caps">Total Floating Amount</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row-xs-height">
<div class="col-xs-height col-top">
<div class="p-l-20 p-t-50 p-b-40 p-r-20">
<h3 class="no-margin p-b-5 text-white">MYR 500,123</h3>
<div class="row-xs-height">
<div class="col-xs-height col-top">
<div class="p-l-20 p-t-50 p-b-40 p-r-20">
<h3 class="no-margin p-b-5 text-white">MYR 500,123</h3>
</div>
</div>
</div>
</div>
</div>
<div class="row-xs-height">
<div class="col-xs-height col-bottom">
<div class="progress progress-small m-b-0">
<div class="progress-bar progress-bar-primary" style="width: 0"></div>
<div class="row-xs-height">
<div class="col-xs-height col-bottom">
<div class="progress progress-small m-b-0">
<div class="progress-bar progress-bar-primary" style="width: 0"></div>
</div>
</div>
</div>
</div>
</div>
@@ -133,43 +138,67 @@
import Chart from 'chart.js';
export default {
data(){
return {
section: 'walletStatsSection',
isLoading: false,
report: {
incomingSum: 0,
outgoingSum: 0,
walletSum: 0
}
}
},
computed: {
pendingQueue () {
return this.$store.getters.isInCompleteQueue(this.section);
},
},
watch: {
wallet_details: function() {
const ctx = document.getElementById('wallets-chart');
var xValues = [100,200,300,400,500,600,700,800,900,1000];
new Chart(ctx, {
type: "line",
data: {
labels: 'ndcs',
datasets: [{
data: [860,1140,1060,1060,1070,1110,1330,2210,7830,2478],
borderColor: "red",
fill: false
},
pendingQueue(inComplete){
if(inComplete){
this.fetchReport();
}
},
},
created(){
this.$store.dispatch('updateListQueue', {'name': this.section});
},
mounted() {
const ctx = document.getElementById('wallets-chart');
new Chart(ctx, {
type: 'pie',
data: {
labels: ['Red', 'Orange', 'Yellow', 'Green', 'Blue'],
datasets: [
{
data: [1600,1700,1700,1900,2000,2700,4000,5000,6000,7000],
borderColor: "green",
fill: false
},
{
data: [300,700,2000,5000,6000,4000,2000,1000,200,100],
borderColor: "blue",
fill: false
}]
},
options: {
responsive: true,
plugins: {
legend: {
position: 'top',
},
title: {
display: true,
text: 'Chart.js Line Chart'
}
label: 'Dataset 1',
data: [1, 1, 1, 1, 1],
}
},
});
]
},
options: {
responsive: true,
plugins: {
legend: {
position: 'top',
},
title: {
display: true,
text: 'Chart.js Pie Chart'
}
}
},
});
},
methods: {
fetchReport(){
this.isLoading = true;
this.submit(route('api.wallet.reports'), 'get', this.section, false, false)
},
successHandler(response){
this.isLoading = false;
this.report = response.payload.data;
}
},
mixins: [componentHandler]
+2
View File
@@ -10,4 +10,6 @@ Route::group(['prefix' => 'wallets', 'namespace' => 'Wallets', 'as' => 'wallet.'
Route::post('/credit', 'CreditWalletController@credit')->name('credit'); // admin +
Route::put('/{transaction_id}/update-status/{status}', 'UpdateStatusWalletController@updateStatus')->where('status', 'approve|reject')->name('approval');
Route::get('/reports', 'WalletReportController@walletsReport')->name('reports');
});