implement api wallets for customer

This commit is contained in:
edmondlang
2022-02-05 18:02:36 +08:00
parent 1e49baa5f1
commit a5c96f4e89
10 changed files with 222 additions and 220 deletions
@@ -15,7 +15,7 @@ use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Http\Resources\WalletResource;
use App\Http\Resources\WalletTransactionResource;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -86,6 +86,7 @@ class TopUpWalletLogic extends AbstractControllerLogic
*/
public function logic(Request $request) : JsonResponse
{
$amount = floatval(str_replace(',', '', $request->input('amount')));
$company = $this->fetchesCompany->execute(['id' => $request->input('company_id')]);
if (!$company->wallets()->first()) {
$object = new WalletObject($company->id, 1, $this->generatesWalletCode->execute());
@@ -99,7 +100,7 @@ class TopUpWalletLogic extends AbstractControllerLogic
$user->name,
$user->email,
'This payment is made for wallet topup. ' . $company->reference,
$request->input('amount'),
$amount,
$billNumber,
$request->input('bank_code')
);
@@ -111,8 +112,8 @@ class TopUpWalletLogic extends AbstractControllerLogic
$company->id,
1,
PaymentMethodType::PAYMENT_GATEWAY,
$request->input('amount'),
$request->input('amount'),
$amount,
$amount,
1,
1,
1,
@@ -126,6 +127,6 @@ class TopUpWalletLogic extends AbstractControllerLogic
$transaction = $this->createsTransaction->execute($company->wallets()->first(), $transaction_object);
return $this->resourceResponse(new WalletResource($wallet));
return $this->resourceResponse(new WalletTransactionResource($transaction));
}
}
@@ -23,7 +23,8 @@ class WalletTransactionResource extends JsonResource
'currency_id' => (int) $this->currency_id,
'original_amount' => (double) $this->original_amount,
'original_currency_id' => (int) $this->original_currency_id,
'currency_rate' => (double) $this->currency_rate
'currency_rate' => (double) $this->currency_rate,
'reference' => $this->payment_reference
];
}
}
@@ -138,10 +138,10 @@
</div>
</div>
</div>
<div class="col-3">
<div class="col">
<div class="row">
<div class="col-10 m-b-15">
<wallet-component></wallet-component>
<div class="col m-b-15">
<wallet-component :data="company"></wallet-component>
</div>
</div>
<booking-form-component :data="company" section="customerProfileSection"></booking-form-component>
@@ -571,7 +571,7 @@
</div>
<div class="col-2 p-l-0 p-r-0 order-last">
<verification-warning-component v-if="!isLoading && company.bookings.length" :data="company"></verification-warning-component>
<wallet-component></wallet-component>
<wallet-component :data="company"></wallet-component>
</div>
</div>
</div>
@@ -0,0 +1,140 @@
<template>
<div class="row">
<div class="col">
<div class="row">
<div class="col-8">
<div class="row p-b-5 b-b b-grey m-b-10 m-l-0 m-r-0">
<div class="col no-padding">
<h6>Transaction History</h6>
</div>
</div>
<div class="row" v-show="company.wallet.length > 0">
<div class="col">
<div class="row padding-10">
<div class="col-2 fs-10">Date</div>
<div class="col fs-10">Description</div>
<div class="col-2 fs-10">Incoming</div>
<div class="col-2 fs-10">Outgoing</div>
<div class="col-2 fs-10">Balance</div>
</div>
<div class="row bg-white padding-10 m-b-10 rounded" v-for="item in company.wallet[0].transactions" v-bind:key="item.id" :data="item">
<div class="col-2">{{item.created_at}}</div>
<div class="col">{{item.type == 5 ? 'Top Up' : 'Payment to bill'}}</div>
<div class="col-2 text-success">{{item.type == 5 ? (Math.round((item.amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") : ''}}</div>
<div class="col-2 text-danger">{{item.type != 5 ? '- ' + (Math.round((item.amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") : ''}}</div>
<div class="col-2">Balance</div>
</div>
</div>
</div>
<div class="row align-items-center justify-content-center p-t-50 p-b-50" v-show="company.wallet.length == 0">
<div class="col-10">
<div class="row align-items-center justify-content-center hint-text">
<div class="col-4 hint-text"><img src="/images/not-found-illustration.png" class="w-100 hint-text"/></div>
</div>
<div class="row text-center">
<div class="col">
<div class="row m-t-20">
<div class="col">
<p class="all-caps no-margin fs-11" style="letter-spacing: 2px;">Nothing To Show Here</p>
</div>
</div>
<div class="row m-t-5 align-items-center justify-content-center">
<div class="col">
<small class="fs-9 muted all-caps font-lato" style="letter-spacing: 2px">There is no results found, Try adjusting your filters to find what you are looking for.</small>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-3 m-l-15">
<wallet-component :data="company"></wallet-component>
<div class="row m-t-20">
<div class="col">
<div class="row m-b-10">
<div class="col">
<div class="font-head fs-10 all-caps">Top Up Records</div>
</div>
</div>
<div class="row" v-show="company.wallet.length > 0">
<div class="col">
<wallet-top-up-history-component v-for="item in company.wallet[0].topup_transactions" v-bind:key="item.id" :data="item"></wallet-top-up-history-component>
</div>
</div>
<div class="row align-items-center justify-content-center p-t-50 p-b-50" v-show="company.wallet.length == 0">
<div class="col-10">
<div class="row align-items-center justify-content-center hint-text">
<div class="col-4 hint-text"><img src="/images/not-found-illustration.png" class="w-100 hint-text"/></div>
</div>
<div class="row text-center">
<div class="col">
<div class="row m-t-20">
<div class="col">
<p class="all-caps no-margin fs-11" style="letter-spacing: 2px;">Nothing To Show Here</p>
</div>
</div>
<div class="row m-t-5 align-items-center justify-content-center">
<div class="col">
<small class="fs-9 muted all-caps font-lato" style="letter-spacing: 2px">There is no results found, Try adjusting your filters to find what you are looking for.</small>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
id: {
type: Number,
required: true
}
},
data(){
return {
section: 'customerTransactionSection',
isLoading: true,
company: null,
attention: false
}
},
computed: {
pendingQueue () {
return this.$store.getters.isInCompleteQueue(this.section);
}
},
watch: {
pendingQueue(inComplete){
if(inComplete){
this.fetchCompany();
}
}
},
created(){
this.$store.dispatch('updateListQueue', {'name': this.section});
},
methods: {
fetchCompany(){
this.isLoading = true;
this.submit(route('api.company.show', this.id), 'get', this.section, false, false)
},
successHandler(response){
this.isLoading = false;
this.company = response.payload.data;
}
}
}
</script>
File diff suppressed because one or more lines are too long
@@ -3,28 +3,26 @@
<div class="col">
<div class="row m-l-0 m-b-10 m-r-0 parentContainer" :class="[{'b-a': item.status === 4}, {'b-danger': item.status === 4}]" >
<div class="col">
<div class="row" v-if="item.type === 3">
<div class="row">
<div class="col">
<div class="row">
<div class="col p-t-10 p-b-10 p-r-0" :class="[{'bg-master-lighter': item.status === 1}, {'bg-white': item.status !== 1 && item.status !== 4}]">
<div class="col p-t-10 p-b-10 p-r-0" :class="[{'bg-master-lighter': item.status === 1 || item.status === 0}, {'bg-white': item.status !== 1 && item.status !== 4}]">
<div class="row m-b-5">
<div class="col-auto">
<div class="font-heading fs-8 muted all-caps">Status</div>
<div class="font-heading fs-10 bold" :class="[{'text-danger': item.status === 1 || item.status === 4}, {'text-success': item.status !== 1 && item.status !== 4}]">
{{ item.status === 1 ? 'Processing Payment' : 'Success'}}
<div class="font-heading fs-10 bold" :class="[{'text-warning': item.status === 0}, {'text-danger': item.status === 1 || item.status === 4}, {'text-success': item.status == 2 && item.status == 3}]">
{{ item.status === 0 ? 'Pedning Verification' : ''}}
</div>
</div>
<div class="col-auto p-l-0">
<div class="font-heading fs-8 muted all-caps">Payment Amount</div>
<div class="font-heading fs-10 bold">
<!-- {{item.original_currency.short_code}} {{(Math.round((item.original_amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}} -->
MYR 1000
MYR {{(Math.round((item.amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
</div>
</div>
</div>
<div class="row m-b-5" v-if="$store.getters.isAdmin">
<!-- <div class="col" v-if="$store.getters.isAdmin && item.type === 3"> -->
<div class="col">
<div class="col" v-if="$store.getters.isAdmin && item.type === 3">
<div class="font-heading fs-8 muted all-caps">Customer Marking</div>
<div class="font-heading fs-10 bold">
Marking & Link
@@ -33,20 +31,20 @@
</div>
<div class="row">
<div class="col">
<!-- <div class="font-heading fs-8 all-caps" >{{ item.status === 1 ? 'Paid On: ' + customerBooking.updated_at : 'Transferred On:' + item.updated_at }}</div> -->
<div class="font-heading fs-8 all-caps">Paid On: 25-12-2021 11:15:45 AM </div>
<div class="font-heading fs-8 all-caps" >{{ item.status === 1 ? 'Created On: ' + item.updated_at : 'Paid On:' + item.updated_at }}</div>
</div>
</div>
</div>
<div class="col-auto pointer" v-if="item.status !== 3 && item.status !== 2" :class="[{'bg-master-light': item.status === 1}, {'bg-master-lighter': item.status === 2}]">
<div class="col-auto pointer" :class="[{'bg-master-light': item.status === 0 || item.status === 1 }, {'bg-master-lighter': item.status === 2}]">
<div class="row align-items-center h-100">
<div class="col">
<i class="fa" :class="[{'fa-cloud-download': item.status === 1 || item.status === 2}, {'fa-ban': item.status === 4}, {'muted': item.status === 1 || item.status === 2}, {'text-danger': item.status === 4}]"></i>
<a :href="'https://www.billplz-sandbox.com/bills/'+item.payment_reference"><i class="fa fa-repeat text-muted"></i></a>
</div>
</div>
</div>
<div class="col-auto bg-success" v-if="item.status === 2 || item.status === 3">
<!-- <document-file-viewer-component class="h-100" :file="item.documents.files[0]">
<document-file-viewer-component class="h-100" :file="item.documents.files[0]">
<template slot="button">
<div class="row align-items-center h-100">
<div class="col">
@@ -54,7 +52,7 @@
</div>
</div>
</template>
</document-file-viewer-component> -->
</document-file-viewer-component>
</div>
</div>
</div>
@@ -70,11 +68,6 @@
export default {
data(){
return {
// expandPaymentDetails: false,
item: {
status: 1,
type: 3
},
}
},
mixins: [componentHandler]
@@ -1,41 +1,66 @@
<template>
<div class="row">
<div class="col bg-white padding-40 b-rad-lg">
<div class="row m-b-10">
<div class="col text-center">
<div class="fs-11">Plese enter the {{topUpType}} amount.</div>
<div class="col">
<div class="row m-t-15">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.amount">
<label>Top Up Amount (MYR)</label>
<input class="form-control" v-model.lazy="parameters.amount" v-money="{decimal: '.',thousands: ',', precision: 2}">
</validation-wrapper-component>
</div>
</div>
<div class="row m-b-20">
<div class="col no-padding">
<div class="form-group form-group-default m-b-0">
<label>Amount</label>
<input type="text" placeholder="0.00" value="0" class="form-control" v-money="money">
</div>
</div>
<div class="row m-t-15 p-l-15 p-r-15">
<div class="col bg-master-lightest b-grey b-a m-l-5 m-r-5 p-t-5 p-b-5 btn-rounded text-center font-heading fs-10 all-caps text-master cursor" :class="[{'bg-info-lighter': parseInt(parameters.amount.replace(/\,/g,'')) == 500}]" @click="updateTopUpAmount(500)">MYR<br>500</div>
<div class="col bg-master-lightest b-grey b-a m-l-5 m-r-5 p-t-5 p-b-5 btn-rounded text-center font-heading fs-10 all-caps text-master cursor" :class="[{'bg-info-lighter': parseInt(parameters.amount.replace(/\,/g,'')) == 1000}]" @click="updateTopUpAmount(1000)">MYR<br>1000</div>
<div class="col bg-master-lightest b-grey b-a m-l-5 m-r-5 p-t-5 p-b-5 btn-rounded text-center font-heading fs-10 all-caps text-master cursor" :class="[{'bg-info-lighter': parseInt(parameters.amount.replace(/\,/g,'')) == 3000}]" @click="updateTopUpAmount(3000)">MYR<br>3000</div>
</div>
<div class="row">
<div class="col-4 p-l-0 p-r-0">
<button class="btn btn-sm all-caps b-rad-none btn-default bg-master-lighter btn-block" data-dismiss="modal">Cancel</button>
</div>
<div class="col p-l-0 p-r-0">
<button class="btn btn-sm all-caps b-rad-none btn-success btn-block">Confirm</button>
<div class="row m-t-10 p-l-15 p-r-15">
<div class="col bg-master-lightest b-grey b-a m-l-5 m-r-5 p-t-5 p-b-5 btn-rounded text-center font-heading fs-10 all-caps text-master cursor" :class="[{'bg-info-lighter': parseInt(parameters.amount.replace(/\,/g,'')) == 5000}]" @click="updateTopUpAmount(5000)">MYR<br>5000</div>
<div class="col bg-master-lightest b-grey b-a m-l-5 m-r-5 p-t-5 p-b-5 btn-rounded text-center font-heading fs-10 all-caps text-master cursor" :class="[{'bg-info-lighter': parseInt(parameters.amount.replace(/\,/g,'')) == 10000}]" @click="updateTopUpAmount(10000)">MYR<br>10000</div>
<div class="col bg-master-lightest b-grey b-a m-l-5 m-r-5 p-t-5 p-b-5 btn-rounded text-center font-heading fs-10 all-caps text-master cursor" :class="[{'bg-info-lighter': parseInt(parameters.amount.replace(/\,/g,'')) == 50000}]" @click="updateTopUpAmount(50000)">MYR<br>50000</div>
</div>
<div class="row m-t-15">
<div class="col">
<div class="btn btn-xs btn-success btn-block b-rad-none rounded" @click="submit(route('api.wallet.topup'), 'post', '', true, true)">Confirm</div>
</div>
</div>
</div>
</div>
</template>
<script>
import ModalFormHandler from '../../../general/mixins/modalFormHandler';
import componentHandler from '../../../general/mixins/componentHandler';
import {VMoney} from 'v-money'
import { required, minValue} from "vuelidate/lib/validators";
export default {
props: {
topUpType:{
type: String,
required: true
data(){
return {
parameters: {
company_id: this.data,
amount: '0.00',
}
}
},
mixins: [ModalFormHandler],
validations () {
return {
parameters: {
amount: {
required,
minValue: 10.00,
}
}
}
},
methods: {
updateTopUpAmount(amount){
this.parameters.amount = (Math.round((amount + Number.EPSILON) * 100) / 100).toFixed(2);
},
successHandler(response){
window.location.href = 'https://www.billplz-sandbox.com/bills/' + response.payload.data.reference + '?auto_submit=true';
},
},
mixins: [componentHandler],
directives: {money: VMoney}
}
</script>
@@ -1,113 +1,5 @@
<div class="row">
<div class="col-8">
<div class="row p-b-5 b-b b-grey m-b-10 m-l-0 m-r-0">
<div class="col no-padding">
<h6>Transaction History</h6>
</div>
</div>
<div class="row padding-10">
<div class="col-2 fs-10">Date</div>
<div class="col fs-10">Description</div>
<div class="col-2 fs-10">Incoming</div>
<div class="col-2 fs-10">Outgoing</div>
<div class="col-2 fs-10">Balance</div>
</div>
<div class="row bg-white padding-10 m-b-10 rounded">
<div class="col-2">25/11/2015</div>
<div class="col">Payment to bill #121221121</div>
<div class="col-2"></div>
<div class="col-2 text-danger">- 2,123</div>
<div class="col-2">12,123</div>
</div>
<div class="row bg-white padding-10 m-b-10 rounded">
<div class="col-2">115/11/2015</div>
<div class="col">Top Up</div>
<div class="col-2 text-success">1,234</div>
<div class="col-2"></div>
<div class="col-2">14,246</div>
</div>
</div>
<div class="col-3 m-l-15">
<wallet-component></wallet-component>
<div class="row m-t-20">
<div class="col">
<div class="row m-b-10">
<div class="col">
<div class="font-head fs-10 all-caps">Top Up Records</div>
</div>
</div>
<!-- start top up records -->
<div class="row m-b-10">
<div class="col bg-white m-l-15 m-r-15 padding-15 rounded">
<div class="row m-l-5">
<div class="col">
<div class="row">
<div class="col">
<div class="text-master fs-11">Payment Method <span class="b-success b-a text-success fs-10 rounded p-l-5 p-r-5 m-l-5 bg-white">Success</span></div>
</div>
<div class="col-auto">
<p>$123,123</p>
</div>
</div>
<div class="row">
<div class="col">
<span class="fs-10">12-03-2021</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row m-b-10">
<div class="col bg-white m-l-15 m-r-15 padding-15 rounded">
<div class="row m-l-5">
<div class="col">
<div class="row">
<div class="col">
<div class="text-master fs-11">Payment Method <span class="b-danger b-a text-danger fs-10 rounded p-l-5 p-r-5 m-l-5 bg-white">Failed</span></div>
</div>
<div class="col-auto">
<p>$123,123</p>
</div>
</div>
<div class="row">
<div class="col">
<span class="fs-10">12-03-2021</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row m-b-10">
<div class="col bg-white m-l-15 m-r-15 padding-15 rounded">
<div class="row m-l-5">
<div class="col">
<div class="row">
<div class="col">
<div class="text-master fs-11">Payment Method <span class="b-info b-a text-info fs-10 rounded p-l-5 p-r-5 m-l-5 bg-white">Processing</span></div>
</div>
<div class="col-auto">
<p>$123,123</p>
</div>
</div>
<div class="row">
<div class="col">
<span class="fs-10">12-03-2021</span>
</div>
</div>
</div>
</div>
</div>
</div>
<wallet-top-up-history-component></wallet-top-up-history-component>
</div>
</div>
<div class="col">
<customer-transaction-section-component :id="{{$id}}"></customer-transaction-section-component>
</div>
</div>
+2 -2
View File
@@ -77,8 +77,8 @@ Route::get('/transfer/merge/{marking}', function ($marking) {
Route::get('/online_payment/redirect', 'Billplz\CallbackBillplzController@callback')->name('online_payment.redirect');
Route::get('/wallet/{marking}/details', function () {
return view('pages.wallet.index');
Route::get('/wallet/{id}/details', function ($id) {
return view('pages.wallet.index', ['id' => $id]);
})->name('wallet.details');
Route::get('/wallets', function () {