Merge remote-tracking branch 'origin/development' into development

This commit is contained in:
omair saleh
2022-02-06 12:30:13 +08:00
45 changed files with 1142 additions and 468 deletions
@@ -53,24 +53,18 @@ class DeleteUserLogic extends AbstractControllerLogic
/**
* @param Request $request
* @return JsonResponse
* @throws ErrorException
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function logic(Request $request) : JsonResponse
{
try {
DB::beginTransaction();
$user = $this->fetchesUser->execute(['id' => $request->route('id')]);
$this->canDeleteUser->passes();
$this->deletesUser->execute($user);
$user = $this->fetchesUser->execute(['id' => $request->route('id')]);
$this->canDeleteUser->passes();
$this->deletesUser->execute($user);
DB::commit();
return $this->resourceResponse(new UserResource($user));
} catch (\Exception $exception){
throw new ErrorException($exception->getMessage(), $exception->getCode());
}
return $this->resourceResponse(new UserResource($user));
}
}
@@ -22,7 +22,7 @@ class AddressObject implements DataTransferObject
/** @var int */
private $districtId;
/** @var int */
/** @var string */
private $postCode;
/**
@@ -32,9 +32,9 @@ class AddressObject implements DataTransferObject
* @param int $countryId
* @param int $stateId
* @param int $districtId
* @param int $postCode
* @param string $postCode
*/
public function __construct(string $streetOne, ?string $streetTwo, int $countryId, int $stateId, int $districtId, int $postCode)
public function __construct(string $streetOne, ?string $streetTwo, int $countryId, int $stateId, int $districtId, string $postCode)
{
$this->streetOne = $streetOne;
$this->streetTwo = $streetTwo;
@@ -85,9 +85,9 @@ class AddressObject implements DataTransferObject
}
/**
* @return int
* @return string
*/
public function getPostCode(): int
public function getPostCode(): string
{
return $this->postCode;
}
@@ -2,6 +2,8 @@
namespace App\Classes\Modules\Billplzs\ControllersLogic;
use App\Classes\Modules\Wallets\DataTransferObjects\WalletObject;
use App\Classes\Modules\Wallets\Services\UpdatesWallet;
use App\Classes\Exceptions\ResourceNotFoundException;
use App\Http\Resources\TransactionResource;
@@ -32,6 +34,8 @@ class CallbackBillplzLogic
/** @var UpdatesTransactionStatus */
private $updatesTransactionStatus;
/** @var UpdatesWallet */
private $updatesWallet;
/**
* CreateBookingLogic constructor.
@@ -39,11 +43,12 @@ class CallbackBillplzLogic
* @param FetchesTransaction $fetchesTransaction
* @param UpdatesTransactionStatus $updatesTransactionStatus
*/
public function __construct(GetBillplzBill $getBillplzBill, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus)
public function __construct(GetBillplzBill $getBillplzBill, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, UpdatesWallet $updatesWallet)
{
$this->getBillplzBill = $getBillplzBill;
$this->fetchesTransaction = $fetchesTransaction;
$this->updatesTransactionStatus = $updatesTransactionStatus;
$this->updatesWallet = $updatesWallet;
}
@@ -55,7 +60,6 @@ class CallbackBillplzLogic
*/
public function execute(Request $request)
{
$billplzXSignatureObject = new BillplzXSignatureObject($request);
if(!$billplzXSignatureObject->isValidSignature()){
@@ -70,13 +74,26 @@ class CallbackBillplzLogic
if($billPlz->state === 'paid') {
$status = ApprovalStatus::APPROVED;
if (
$transaction->owner_type == 'App\Models\Wallet' &&
$transaction->status == ApprovalStatus::PENDING_VERIFICATION
) {
$wallet = $transaction->owner;
$updateWalletAmount = $wallet->amount + $transaction->amount;
$walletOject = new WalletObject($wallet->company->id, $wallet->currency_id, $wallet->code, $updateWalletAmount);
$wallet = $this->updatesWallet->execute($wallet, $walletOject);
}
}
if($billPlz->state === 'due') {
$status = $billplzXSignatureObject->getStatus() === 'failed' ? ApprovalStatus::REJECTED : ApprovalStatus::PENDING_VERIFICATION;
}
$this->updatesTransactionStatus->execute($transaction, $status);
if($transaction->status !== ApprovalStatus::COMPLETED){
$this->updatesTransactionStatus->execute($transaction, $status);
}
$token = Auth::fromUser(User::find(1));
$request->headers->set('Authorization', 'Bearer '.$token);
@@ -78,6 +78,7 @@ class RegenerateInvoiceBookingLogic extends AbstractControllerLogic
* @param Request $request
* @return JsonResponse
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function logic(Request $request) : JsonResponse
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\Bookings\Standards\Rules;
use App\Classes\General\Abstracts\AbstractRule;
use App\Classes\Modules\Bookings\DataTransferObjects\BookingObject;
use Illuminate\Support\Facades\Auth;
class CanDeleteBooking extends AbstractRule
{
@@ -14,7 +15,7 @@ class CanDeleteBooking extends AbstractRule
{
// TODO Set Authorization rules
if (!\Auth::user()->can('delete booking')) {
if (!Auth::user()->can('delete booking')) {
return false;
}
@@ -5,6 +5,7 @@ namespace App\Classes\Modules\Bookings\Standards\Rules;
use App\Classes\General\Abstracts\AbstractRule;
use App\Classes\Modules\Bookings\Standards\Validators\BookingValidation;
use Illuminate\Support\Facades\Auth;
class CanUpdateBooking extends AbstractRule
{
@@ -29,7 +30,7 @@ class CanUpdateBooking extends AbstractRule
{
// TODO Set Authorization rules
if (!\Auth::user()->can('edit booking')) {
if (!Auth::user()->can('edit booking')) {
return false;
}
@@ -5,6 +5,7 @@ namespace App\Classes\Modules\Currencies\Standards\Rules\Rates;
use App\Classes\General\Abstracts\AbstractRule;
use App\Classes\Modules\Currencies\Standards\Validators\Rates\RateValidation;
use App\Classes\Modules\Currencies\DataTransferObjects\RateObject;
use Illuminate\Support\Facades\Auth;
class CanCreateRate extends AbstractRule
{
@@ -27,7 +28,7 @@ class CanCreateRate extends AbstractRule
protected function authorized(): bool
{
// TODO Set Authorization rules
if (!\Auth::user()->can('add currency_rate')) {
if (!Auth::user()->can('add currency_rate')) {
return false;
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\Currencies\Standards\Rules\Rates;
use App\Classes\General\Abstracts\AbstractRule;
use App\Classes\Modules\Currencies\DataTransferObjects\RateObject;
use Illuminate\Support\Facades\Auth;
class CanDeleteRate extends AbstractRule
{
@@ -14,7 +15,7 @@ class CanDeleteRate extends AbstractRule
{
// TODO Set Authorization rules
if (!\Auth::user()->can('delete currency_rate')) {
if (!Auth::user()->can('delete currency_rate')) {
return false;
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\Currencies\Standards\Rules\Rates;
use App\Classes\General\Abstracts\AbstractRule;
use App\Classes\Modules\Currencies\DataTransferObjects\CurrencyObject;
use Illuminate\Support\Facades\Auth;
class CanListRates extends AbstractRule
{
@@ -14,7 +15,7 @@ class CanListRates extends AbstractRule
{
// TODO Set Authorization rules
if (!\Auth::user()->can('view currency_rate')) {
if (!Auth::user()->can('view currency_rate')) {
return false;
}
@@ -6,6 +6,7 @@ namespace App\Classes\Modules\Currencies\Standards\Rules\Rates;
use App\Classes\General\Abstracts\AbstractRule;
use App\Classes\Modules\Currencies\Standards\Validators\Rates\RateValidation;
use App\Classes\Modules\Currencies\DataTransferObjects\RateObject;
use Illuminate\Support\Facades\Auth;
class CanUpdateRate extends AbstractRule
{
@@ -29,7 +30,7 @@ class CanUpdateRate extends AbstractRule
{
// TODO Set Authorization rules
if (!\Auth::user()->can('view currency_rate')) {
if (!Auth::user()->can('view currency_rate')) {
return false;
}
@@ -5,6 +5,7 @@ namespace App\Classes\Modules\Segments\Standards\Rules;
use App\Classes\General\Abstracts\AbstractRule;
use App\Classes\Modules\Segments\DataTransferObjects\SegmentObject;
use App\Classes\Modules\Segments\Standards\Validators\SegmentValidation;
use Illuminate\Support\Facades\Auth;
class CanCreateSegment extends AbstractRule
{
@@ -27,7 +28,7 @@ class CanCreateSegment extends AbstractRule
protected function authorized(): bool
{
// TODO Set Authorization rules
if (!\Auth::user()->can('add segment')) {
if (!Auth::user()->can('add segment')) {
return false;
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\Segments\Standards\Rules;
use App\Classes\General\Abstracts\AbstractRule;
use App\Classes\Modules\Segments\DataTransferObjects\SegmentObject;
use Illuminate\Support\Facades\Auth;
class CanDeleteSegment extends AbstractRule
{
@@ -14,7 +15,7 @@ class CanDeleteSegment extends AbstractRule
{
// TODO Set Authorization rules
if (!\Auth::user()->can('delete segment')) {
if (!Auth::user()->can('delete segment')) {
return false;
}
@@ -6,6 +6,7 @@ namespace App\Classes\Modules\Segments\Standards\Rules;
use App\Classes\General\Abstracts\AbstractRule;
use App\Classes\Modules\Segments\DataTransferObjects\SegmentObject;
use App\Classes\Modules\Segments\Standards\Validators\SegmentValidation;
use Illuminate\Support\Facades\Auth;
class CanUpdateSegment extends AbstractRule
{
@@ -30,7 +31,7 @@ class CanUpdateSegment extends AbstractRule
{
// TODO Set Authorization rules
if (!\Auth::user()->can('edit segment')) {
if (!Auth::user()->can('edit segment')) {
return false;
}
@@ -0,0 +1,128 @@
<?php
namespace App\Classes\Modules\Wallets\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Wallets\DataTransferObjects\WalletObject;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\Modules\Wallets\Services\CreatesWallet;
use App\Classes\Modules\Wallets\Services\GeneratesWalletCode;
use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber;
use App\Classes\Modules\Transactions\Services\CreatesTransaction;
use App\Classes\Modules\Wallets\Services\UpdatesWallet;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Http\Resources\WalletResource;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class CreditWalletLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Credit into Company Wallet',
'message' => 'You have successfully credit company wallet'
];
}
/** @var FetchesCompany */
private $fetchesCompany;
/** @var GeneratesWalletCode */
private $generatesWalletCode;
/** @var CreatesWallet */
private $createsWallet;
/** @var GeneratesTransactionBillNumber */
private $generatesTransactionBillNumber;
/** @var CreatesTransaction */
private $createsTransaction;
/** @var UpdatesWallet */
private $updatesWallet;
/**
* CreateWalletLogic constructor.
* @param FetchesCompany $fetchesCompany
* @param GeneratesWalletCode $generatesWalletCode
* @param CreatesWallet $createsWallet
* @param GeneratesTransactionBillNumber $generatesTransactionBillNumber
* @param CreatesTransaction $createsTransaction
* @param UpdatesWallet $updatesWallet
*/
public function __construct(
FetchesCompany $fetchesCompany,
GeneratesWalletCode $generatesWalletCode,
CreatesWallet $createsWallet,
GeneratesTransactionBillNumber $generatesTransactionBillNumber,
CreatesTransaction $createsTransaction,
UpdatesWallet $updatesWallet
)
{
$this->fetchesCompany = $fetchesCompany;
$this->generatesWalletCode = $generatesWalletCode;
$this->createsWallet = $createsWallet;
$this->generatesTransactionBillNumber = $generatesTransactionBillNumber;
$this->createsTransaction = $createsTransaction;
$this->updatesWallet = $updatesWallet;
}
/**
* @param Request $request
* @return JsonResponse
* @throws ErrorException
*/
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());
$wallet = $this->createsWallet->execute($object, $company);
}
$wallet = $company->wallets()->first();
$billNumber = $this->generatesTransactionBillNumber->execute('CREDIT-NOTE-');
$transaction_object = new TransactionObject(
$billNumber,
TransactionType::CREDIT_NOTE,
1,
$wallet->company->id,
1,
PaymentMethodType::WALLET,
$amount,
$amount,
1,
1,
1,
0,
0,
null,
ApprovalStatus::PENDING_SUBMISSION,
[]
);
$transaction = $this->createsTransaction->execute($wallet, $transaction_object);
$updateWalletAmount = $wallet->amount + $transaction->amount;
$walletOject = new WalletObject($wallet->company->id, $wallet->currency_id, $wallet->code, $updateWalletAmount);
$wallet = $this->updatesWallet->execute($wallet, $walletOject);
return $this->resourceResponse(new WalletResource($wallet));
}
}
@@ -0,0 +1,114 @@
<?php
namespace App\Classes\Modules\Wallets\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Wallets\DataTransferObjects\WalletObject;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber;
use App\Classes\Modules\Transactions\Services\CreatesTransaction;
use App\Classes\Modules\Wallets\Services\UpdatesWallet;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Http\Resources\WalletResource;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class DebitWalletLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Debit into Company Wallet',
'message' => 'You have successfully debit company wallet'
];
}
/** @var FetchesCompany */
private $fetchesCompany;
/** @var GeneratesTransactionBillNumber */
private $generatesTransactionBillNumber;
/** @var CreatesTransaction */
private $createsTransaction;
/** @var UpdatesWallet */
private $updatesWallet;
/**
* CreateWalletLogic constructor.
* @param FetchesCompany $fetchesCompany
* @param GeneratesTransactionBillNumber $generatesTransactionBillNumber
* @param CreatesTransaction $createsTransaction
* @param UpdatesWallet $updatesWallet
*/
public function __construct(
FetchesCompany $fetchesCompany,
GeneratesTransactionBillNumber $generatesTransactionBillNumber,
CreatesTransaction $createsTransaction,
UpdatesWallet $updatesWallet
)
{
$this->fetchesCompany = $fetchesCompany;
$this->generatesTransactionBillNumber = $generatesTransactionBillNumber;
$this->createsTransaction = $createsTransaction;
$this->updatesWallet = $updatesWallet;
}
/**
* @param Request $request
* @return JsonResponse
* @throws ErrorException
*/
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());
$wallet = $this->createsWallet->execute($object, $company);
}
$wallet = $company->wallets()->first();
$billNumber = $this->generatesTransactionBillNumber->execute('DEBIT-NOTE-');
$transaction_object = new TransactionObject(
$billNumber,
TransactionType::DEBIT_NOTE,
1,
$wallet->company->id,
1,
PaymentMethodType::WALLET,
$amount,
$amount,
1,
1,
1,
0,
0,
null,
ApprovalStatus::PENDING_SUBMISSION,
[]
);
$transaction = $this->createsTransaction->execute($wallet, $transaction_object);
$updateWalletAmount = $wallet->amount - $transaction->amount;
$walletOject = new WalletObject($wallet->company->id, $wallet->currency_id, $wallet->code, $updateWalletAmount);
$wallet = $this->updatesWallet->execute($wallet, $walletOject);
return $this->resourceResponse(new WalletResource($wallet));
}
}
@@ -3,16 +3,19 @@
namespace App\Classes\Modules\Wallets\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Wallets\DataTransferObjects\WalletObject;
use App\Classes\Modules\Wallets\Services\ListsWallet;
use App\Classes\Modules\Wallets\Services\FetchesWallet;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\Modules\Wallets\Services\CreatesWallet;
use App\Classes\Modules\Wallets\Services\GeneratesWalletCode;
use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber;
use App\Classes\Modules\Billplzs\Services\CreatesBillplzBill;
use App\Classes\Modules\Transactions\Services\CreatesTransaction;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\Modules\Wallets\Standards\Rules\CanTopUpWallet;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Http\Resources\WalletResource;
use App\Classes\Modules\Transactions\Processors\CreateWalletTransactionProcessor;
use App\Http\Resources\WalletTransactionResource;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -30,26 +33,50 @@ class TopUpWalletLogic extends AbstractControllerLogic
];
}
/** @var FetchesWallet */
private $fetchesWallet;
/** @var CanTopUpWallet */
private $canTopUpWallet;
/** @var FetchesCompany */
private $fetchesCompany;
/** @var CreateWalletTransactionProcessor */
private $createWalletTransactionProcessor;
/** @var GeneratesWalletCode */
private $generatesWalletCode;
/** @var CreatesWallet */
private $createsWallet;
/** @var GeneratesTransactionBillNumber */
private $generatesTransactionBillNumber;
/** @var CreatesWalletTransaction */
private $createsWalletTransaction;
/** @var CreatesBillplzBill */
private $createsBillplzBill;
/** @var CreatesTransaction */
private $createsTransaction;
/**
* CreateWalletLogic constructor.
* @param CreatesWallet $createsWallet
* @param FetchesCompany $fetchesCompany
* @param GeneratesWalletCode $generatesWalletCode
* @param CanCreateCompanyWallet $canCreateCompanyWallet
* @param CreatesWallet $createsWallet
* @param GeneratesTransactionBillNumber $generatesTransactionBillNumber
*/
public function __construct(CanTopUpWallet $canTopUpWallet, FetchesWallet $fetchesWallet, CreateWalletTransactionProcessor $createWalletTransactionProcessor)
public function __construct(
FetchesCompany $fetchesCompany,
GeneratesWalletCode $generatesWalletCode,
CreatesWallet $createsWallet,
GeneratesTransactionBillNumber $generatesTransactionBillNumber,
CreatesBillplzBill $createsBillplzBill,
CreatesTransaction $createsTransaction
)
{
$this->canTopUpWallet = $canTopUpWallet;
$this->fetchesWallet = $fetchesWallet;
$this->createWalletTransactionProcessor = $createWalletTransactionProcessor;
$this->fetchesCompany = $fetchesCompany;
$this->generatesWalletCode = $generatesWalletCode;
$this->createsWallet = $createsWallet;
$this->generatesTransactionBillNumber = $generatesTransactionBillNumber;
$this->createsBillplzBill = $createsBillplzBill;
$this->createsTransaction = $createsTransaction;
}
/**
@@ -59,14 +86,49 @@ class TopUpWalletLogic extends AbstractControllerLogic
*/
public function logic(Request $request) : JsonResponse
{
$wallet = $this->fetchesWallet->execute(['id' => $request->input('wallet_id')]);
$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());
$wallet = $this->createsWallet->execute($object, $company);
}
$wallet = $company->wallets()->first();
$walletOject = new WalletObject( $wallet->company->id, $wallet->currency_id, $wallet->code, $request->input('amount'));
$user = $company->employees()->first();
$billNumber = $this->generatesTransactionBillNumber->execute('TOPUP-');
$billPlzBill = $this->createsBillplzBill->execute(
$user->name,
$user->email,
'This payment is made for wallet topup. ' . $company->reference,
$amount,
$billNumber,
$request->input('bank_code')
);
$this->canTopUpWallet->passes($walletOject);
$transaction_object = new TransactionObject(
$billNumber,
TransactionType::TOP_UP,
1,
$company->id,
1,
PaymentMethodType::PAYMENT_GATEWAY,
$amount,
$amount,
1,
1,
1,
0,
0,
null,
ApprovalStatus::PENDING_SUBMISSION,
[],
$billPlzBill->id
);
$transaction = $this->createWalletTransactionProcessor->execute($wallet, $walletOject, TransactionType::TOP_UP);
$transaction = $this->createsTransaction->execute($company->wallets()->first(), $transaction_object);
return $this->resourceResponse(new WalletResource($wallet));
return $this->resourceResponse(new WalletTransactionResource($transaction));
}
}
@@ -21,8 +21,6 @@ class CreatesWallet extends AbstractUpdateRelationshipRecord
$model->code = $object->getCode();
$model->currency_id = $object->getCurrency();
return $this->handler($company->wallets(), $model);
}
}
@@ -24,5 +24,7 @@ final class TransactionType {
public const CREDIT_NOTE = 9;
public const DEBIT_NOTE = 11;
public const WITHDRAW = 10;
}
@@ -0,0 +1,15 @@
<?php
namespace App\Http\Controllers\Wallets;
use App\Classes\Modules\Wallets\ControllersLogic\CreditWalletLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class CreditWalletController
{
public function credit(Request $request, CreditWalletLogic $logic): JsonResponse {
return $logic->execute($request);
}
}
@@ -0,0 +1,15 @@
<?php
namespace App\Http\Controllers\Wallets;
use App\Classes\Modules\Wallets\ControllersLogic\DebitWalletLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class DebitWalletController
{
public function debit(Request $request, DebitWalletLogic $logic): JsonResponse {
return $logic->execute($request);
}
}
+1 -3
View File
@@ -60,10 +60,8 @@ class CompanyResource extends JsonResource
$segment = SegmentConstant::where('reference', SegmentConstants::SUPPLIER_CURRENCIES)->where('detail->id', $this->id)->first();
return $segment ? CurrencyResource::collection(Currency::whereIn('id', $segment->detail->currencies)->get()) : [];
}),
'wallet' => WalletResource::collection($this->wallets),
'created_at' => $this->created_at->format('d-m-Y')
];
}
}
+12 -2
View File
@@ -35,9 +35,19 @@ class TransactionResource extends JsonResource
'status' => (int) $this->status,
'details' => TransactionDetailResource::collection($this->transactionDetails),
'documents' => new DocumentResource($this->documents()->first()),
'customer_booking' => new TransactionResource($this->when((int) $this->type === TransactionType::BILL, $this->booking->transactions()->payments()->complete()->where('original_amount', '=', $this->original_amount)->where('id', '<', $this->id)->orderByDesc('id')->first())),
'customer_booking' => new TransactionResource($this->when((int) $this->type === TransactionType::BILL, function(){
$key = 0;
$bills = $this->booking->transactions()->bills()->where('original_amount', '=', $this->original_amount)->get();
if(count($bills) > 1){ $key = $bills->search(function($bill){ return $bill->id === $this->id; }); }
return $this->booking->transactions()->payments()->complete()->where('original_amount', '=', $this->original_amount)->skip($key)->first();
})),
'expires_on' => Carbon::parse($this->expires_on)->format('d-m-Y h:i:s A'),
'updated_at' => Carbon::parse($this->updated_at)->format('d-m-Y h:i:s A')
'updated_at' => Carbon::parse($this->updated_at)->format('d-m-Y h:i:s A'),
'interval' => [
'value' => (Carbon::parse($this->created_at)->addDays(3)->gt(Carbon::now()) ) ? '+' : '-' ,
'duration' => Carbon::parse($this->created_at)->addDays(3)->diff(Carbon::now())->format('%d'),
],
];
}
}
+12 -1
View File
@@ -2,6 +2,7 @@
namespace App\Http\Resources;
use App\Classes\ValueObjects\Constants\TransactionType;
use Illuminate\Http\Resources\Json\JsonResource;
class WalletResource extends JsonResource
@@ -19,7 +20,17 @@ class WalletResource extends JsonResource
'code' => $this->code,
'currency_id' => $this->currency_id,
'amount' => (double) $this->amount,
'company_id' => (int) $this->company_id
'company_id' => (int) $this->owner->id,
'transactions' => $this->transactions()->orderBy('id', 'DESC')->get(),
'topup_transactions' => $this->transactions()->where('type', TransactionType::TOP_UP)->orderBy('id', 'DESC')->get(),
// 'transaction' => $this->whenLoaded('transactions', function() {
// return [
// 'topup' => $this->transactions
// ];
// }),
// 'transaction' // all
// 'top_transaction' // only topup
];
}
}
@@ -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
];
}
}
+2 -1
View File
@@ -5,6 +5,7 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Spatie\Permission\Traits\HasRoles;
use Tymon\JWTAuth\Contracts\JWTSubject;
@@ -23,7 +24,7 @@ class User extends AbstractModel implements
AuthorizableContract,
CanResetPasswordContract
{
use HasRoles, Notifiable, Authenticatable, Authorizable, CanResetPassword, MustVerifyEmail;
use HasRoles, Notifiable, Authenticatable, Authorizable, CanResetPassword, MustVerifyEmail, SoftDeletes;
/**
+2 -1
View File
@@ -2,13 +2,14 @@
namespace App\Models;
use App\Classes\General\Interfaces\Transactionable;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphMany;
class Wallet extends AbstractModel
class Wallet extends AbstractModel implements Transactionable
{
use SoftDeletes;
@@ -1,196 +0,0 @@
<template>
<div class="row h-100 parentContainer">
<div class="col">
<div class="col-auto p-l-0 p-r-10">
<div class="btn btn-xs btn-primary p-t-0 p-b-0 text-primary-lighter requestModal" style="background-color: rgba(255, 255, 255, 0.2);" data-type="topUpModal">
<i class="fa fa-plus fs-14 m-t-5"></i>
</div>
</div>
<modal-component styleType="fill-in" type="topUpModal">
<div class="row zig-zag-top">
<div class="col bg-white padding-25">
<div class="row m-b-20">
<div class="col">
<div class="row">
<div class="col-8">
<div class="btn btn-xs btn-complete no-border btn-block text-left b-rad-none p-t-0 p-b-0 p-l-15 p-r-15" @click="paymentMethod.status = !paymentMethod.status">
<div class="row">
<div class="col p-t-10 p-b-10">
{{paymentMethod.name}}
</div>
<div class="col-auto bg-complete-light">
<div class="row h-100 align-items-center">
<div class="col">
<i class="fa" :class="[{'fa-angle-down': !paymentMethod.status}, {'fa-angle-up': paymentMethod.status}]"></i>
</div>
</div>
</div>
</div>
</div>
<div class="relative w-100">
<div class="absolute w-100 b-l b-b b-r b-complete" :class="[{'hide': !paymentMethod.status}]" style="top: 100%; right: 0; z-index: 1;">
<div class="row text-left no-margin bg-white">
<div class="col no-padding">
<div class="row no-margin" :class="[{'bg-complete-light': paymentMethod.name === 'Bank Transfer'}, {'text-white': paymentMethod.name === 'Bank Transfer'}, {'hover-complete': paymentMethod.name !== 'Bank Transfer'}]" @click="updatePaymentType({name: 'Bank Transfer', id: 'cash'})">
<div class="col b-b b-grey p-t-10 p-b-10 pointer hover-t-10 p-b-10">
<div class="row align-items-center justify-content-center">
<div class="col">
<div class="font-heading fs-10">Bank Transfer</div>
</div>
</div>
</div>
</div>
<div class="row no-margin" :class="[{'bg-complete-light': paymentMethod.name === 'Cash Deposit'}, {'text-white': paymentMethod.name === 'Cash Deposit'}, {'hover-complete': paymentMethod.name !== 'Cash Deposit'}]" @click="updatePaymentType({name: 'Cash Deposit', id: 'cash'})">
<div class="col b-b b-grey p-t-10 p-b-10 pointer hover-t-10 p-b-10">
<div class="row align-items-center justify-content-center">
<div class="col">
<div class="font-heading fs-10">Cash Deposit</div>
</div>
</div>
</div>
</div>
<div class="row no-margin" :class="[{'bg-complete-light': paymentMethod.name === 'Cheque'}, {'text-white': paymentMethod.name === 'Cheque'}, {'hover-complete': paymentMethod.name !== 'Cheque'}]" @click="updatePaymentType({name: 'Cheque', id: 'cheque'})">
<div class="col b-b b-grey p-t-10 p-b-10 pointer hover-t-10 p-b-10">
<div class="row align-items-center justify-content-center">
<div class="col">
<div class="font-heading fs-10">Cheque</div>
</div>
</div>
</div>
</div>
<div class="row no-margin" :class="[{'bg-complete-light': paymentMethod.name === 'Banker\'s Acceptance'}, {'text-white': paymentMethod.name === 'Banker\'s Acceptance'}, {'hover-complete': paymentMethod.name !== 'Banker\'s Acceptance'}]" @click="updatePaymentType({name: 'Banker\'s Acceptance', id: 'ba'})">
<div class="col b-b b-grey p-t-10 p-b-10 pointer hover-t-10 p-b-10">
<div class="row align-items-center justify-content-center">
<div class="col">
<div class="font-heading fs-10">Banker's Acceptance</div>
</div>
</div>
</div>
</div>
<div class="row no-margin" :class="[{'bg-complete-light': paymentMethod.name === 'Online Transfer'}, {'text-white': paymentMethod.name === 'Online Transfer'}, {'hover-complete': paymentMethod.name !== 'Online Transfer'}]" @click="updatePaymentType({name: 'Online Transfer', id: 'ot'})">
<div class="col b-b b-grey p-t-10 p-b-10 pointer hover-t-10 p-b-10">
<div class="row align-items-center justify-content-center">
<div class="col">
<div class="font-heading fs-10">Online Transfer</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row m-r-0">
<div class="col p-r-0">
<validation-wrapper-component :validator="$v.amount">
<label>Amount</label>
<input class="form-control" name="amount" v-model.lazy="amount">
<!-- <input class="form-control" name="amount" v-model.lazy="amount" v-money="{decimal: '.',thousands: ',', precision: 2}"> -->
</validation-wrapper-component>
</div>
<div class="col-auto b-r b-t b-b b-grey">
<div class="row h-100 align-items-center">
<div class="col">
<!-- <div class="font-heading fs-10 muted">{{this.data.fixed_currency.short_code}}</div> -->
</div>
</div>
</div>
</div>
<div class="row" v-if="paymentMethod.name == 'Online Transfer'">
<div class="col">
<div class="row m-t-10">
<div class="col">
<div class="row">
<div class="col-8">
<div class="btn btn-xs btn-block text-left b-rad-none p-t-10 p-b-10 p-l-15 p-r-15" :class="[{'b-complete': onlinePayment.bankName === 'Maybank'}]" @click="selectOnlinePaymentBank({bankName: 'Maybank', id: 'maybank'})">
<img src="https://shopee.com.my/static/images/bank_logo/img_bankmy_maybank.png" alt="">
Maybank2u
</div>
</div>
</div>
</div>
</div>
<div class="row m-t-10">
<div class="col">
<div class="row">
<div class="col-8">
<div class="btn btn-xs btn-block text-left b-rad-none p-t-10 p-b-10 p-l-15 p-r-15" :class="[{'b-complete': onlinePayment.bankName === 'Cimb'}]" @click="selectOnlinePaymentBank({bankName: 'Cimb', id: 'cimb'})">
<img src="https://shopee.com.my/static/images/bank_logo/img_bankmy_cimb.png" alt="">
Cimb
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-4 p-r-0">
<button class="btn btn-xs all-caps b-rad-none btn-default bg-master-lighter btn-block" data-dismiss="modal">Cancel</button>
</div>
<div class="col p-l-0">
<button class="btn btn-xs all-caps b-rad-none btn-success btn-block" v-if="!(paymentMethod.name === 'Online Transfer' && onlinePayment.status === false)" @click="submitForm()">Confirm</button>
</div>
</div>
</div>
</div>
</modal-component>
</div>
</div>
</template>
<script>
import { required } from "vuelidate/lib/validators";
export default {
data(){
return {
loading: false,
// amount: (Math.round((this.data.outstanding_amount + Number.EPSILON) * 100) / 100).toFixed(2),
amount: (Math.round(1000 * 100) / 100).toFixed(2),
paymentMethod: {
name: 'Bank Transfer',
id: 'cash',
status: false
},
onlinePayment: {
bankName: '',
id: '',
status: false
},
}
},
validations () {
return {
amount: { required }
}
},
methods:{
updatePaymentType(payment){
this.paymentMethod = {
name: payment.name,
id: payment.id,
status: false,
}
},
selectOnlinePaymentBank(bankName){
this.onlinePayment = {
bankName: bankName.bankName,
id: bankName.id,
status: true,
}
},
}
}
</script>
@@ -68,6 +68,14 @@
{{item.original_currency.short_code}} {{(Math.round((item.original_amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
</div>
</div>
<div class="col text-lg-right">
<div class="font-heading fs-10 muted all-caps">Service</div>
<div class="font-heading fs-10">
{{item.booking.service.name}}
</div>
</div>
</div>
<div class="row m-t-10">
<div v-if="!no_action" class="col-6 col-md-auto text-right">
<button class="btn btn-xs btn-outline-danger b-rad-none m-r-5 requestModal" data-type="rejectPayment">
<i class="fa fa-times fa-fw"></i>
@@ -46,6 +46,12 @@
</a>
</div>
</div>
<div class="col-auto">
<div class="font-heading fs-10 muted all-caps">Service</div>
<div class="font-heading fs-10">
{{item.booking.service.name}}
</div>
</div>
</div>
<div class="row">
<div class="col-auto">
@@ -60,12 +66,20 @@
<span class="flag-icon" :class="'flag-icon-'+item.original_currency.country.short_code.toLowerCase()"></span> {{item.original_currency.short_code}}
</div>
</div>
<div class="col">
<div class="col-auto">
<div class="font-heading fs-10 muted all-caps">Amount</div>
<div class="font-heading fs-12 text-success bold">
{{(Math.round((item.original_amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
</div>
</div>
<div class="col">
<div class="font-heading fs-10 muted all-caps">timer</div>
<div class="font-heading fs-10" :class="[{'text-success': item.interval.value === '+'}, {'text-danger': item.interval.value === '-'}]">
{{item.interval.value}}
{{item.interval.duration}}
days
</div>
</div>
</div>
</div>
</div>
File diff suppressed because one or more lines are too long
@@ -369,6 +369,7 @@
</div>
<div class="col p-l-0 col-sm-2 col-md-2">
<verification-warning-component :data="booking.company"></verification-warning-component>
<wallet-component :data="booking.company"></wallet-component>
</div>
</div>
</div>
@@ -8,30 +8,30 @@
<div class="row m-b-15">
<div class="col">
<div class="row">
<div class="col-8 p-r-0">
<div class="btn btn-xs btn-outline-primary btn-block text-left b-rad-none p-t-0 p-b-0 p-l-15 p-r-15" @click="selectedSupplier.status = !selectedSupplier.status">
<div class="col p-r-0">
<div class="btn btn-xs btn-outline-primary btn-block text-left b-rad-none p-t-0 p-b-0 p-l-15 p-r-15" @click="serviceDropdownLaunch.status = ! serviceDropdownLaunch.status">
<div class="row">
<div class="col p-t-5 p-b-5 fs-9">
{{selectedSupplier.name}}
<div class="col p-t-5 p-b-5">
{{selectedService.name}}
</div>
<div class="col-auto b-l b-success">
<div class="col-auto b-l b-primary">
<div class="row h-100 align-items-center">
<div class="col">
<i class="fa" :class="[{'fa-angle-down': !selectedSupplier.status}, {'fa-angle-up': selectedSupplier.status}]"></i>
<i class="fa" :class="[{'fa-angle-down': !serviceDropdownLaunch.status}, {'fa-angle-up': serviceDropdownLaunch.status}]"></i>
</div>
</div>
</div>
</div>
</div>
<div class="relative w-100">
<div class="absolute w-100 b-l b-b b-r b-primary" :class="[{'hide': !selectedSupplier.status}]" style="top: 100%; right: 0; z-index: 1;">
<div class="absolute w-100 b-l b-b b-r b-success" v-show="serviceDropdownLaunch.status" style="top: 100%; right: 0; z-index: 1;">
<div class="row text-left no-margin bg-white">
<div class="col no-padding">
<div class="row no-margin" v-for="supplier in suppliers" v-bind:key="supplier.id" :data="supplier">
<div class="col b-b b-grey p-t-10 p-b-10 pointer hover-t-10 p-b-10" :class="[{'bg-primary-light': selectedSupplier.id === supplier.id}, {'text-white': selectedSupplier.id === supplier.id}, {'hover-primary': selectedSupplier.id !== supplier.id}, {'pointer': selectedSupplier.id !== supplier.id}]" @click="updateSupplier(supplier)">
<div class="row no-margin" v-for="service in selectedSupplier.services" v-bind:key="service.id" :data="service">
<div class="col b-b b-grey p-t-10 p-b-10 pointer hover-t-10 p-b-10" :class="[{'bg-primary-light': selectedService.id === service.id}, {'text-white': selectedService.id === service.id}, {'hover-primary': selectedService.id !== service.id}, {'pointer': selectedService.id !== service.id}]" @click="updateService(service)">
<div class="row align-items-center justify-content-center">
<div class="col">
<div class="font-heading fs-10">{{supplier.name}}</div>
<div class="font-heading fs-10">{{service.name}}</div>
</div>
</div>
</div>
@@ -41,7 +41,7 @@
</div>
</div>
</div>
<div class="col-4 p-r-0">
<div class="col p-r-0">
<div class="btn btn-xs btn-outline-primary btn-block text-left b-rad-none p-t-0 p-b-0 p-l-15 p-r-15" @click="currencyDropdownLaunch.status = ! currencyDropdownLaunch.status">
<div class="row">
<div class="col p-t-5 p-b-5">
@@ -75,11 +75,46 @@
</div>
</div>
</div>
<div class="row m-t-5">
<div class="col p-r-0">
<div class="btn btn-xs btn-outline-primary btn-block text-left b-rad-none p-t-0 p-b-0 p-l-15 p-r-15" @click="selectedSupplier.status = !selectedSupplier.status">
<div class="row">
<div class="col p-t-5 p-b-5 fs-9">
{{selectedSupplier.name}}
</div>
<div class="col-auto b-l b-success">
<div class="row h-100 align-items-center">
<div class="col">
<i class="fa" :class="[{'fa-angle-down': !selectedSupplier.status}, {'fa-angle-up': selectedSupplier.status}]"></i>
</div>
</div>
</div>
</div>
</div>
<div class="relative w-100">
<div class="absolute w-100 b-l b-b b-r b-primary" :class="[{'hide': !selectedSupplier.status}]" style="top: 100%; right: 0; z-index: 1;">
<div class="row text-left no-margin bg-white">
<div class="col no-padding">
<div class="row no-margin" v-for="supplier in suppliers" v-bind:key="supplier.id" :data="supplier">
<div class="col b-b b-grey p-t-10 p-b-10 pointer hover-t-10 p-b-10" :class="[{'bg-primary-light': selectedSupplier.id === supplier.id}, {'text-white': selectedSupplier.id === supplier.id}, {'hover-primary': selectedSupplier.id !== supplier.id}, {'pointer': selectedSupplier.id !== supplier.id}]" @click="updateSupplier(supplier)">
<div class="row align-items-center justify-content-center">
<div class="col">
<div class="font-heading fs-10">{{supplier.name}}</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col">
<list-component ref="pendingOrdersList" section="pendingOrdersSection" :endpoint="route('api.transaction.list')" :options="{per_page: 10000, status: 2, type: 1, original_currency_id_in: [selectedCurrency.id]}">
<list-component ref="pendingOrdersList" section="pendingOrdersSection" :endpoint="route('api.transaction.list')" :options="{per_page: 10000, status: 2, type: 1, original_currency_id_in: [selectedCurrency.id], service_type_id_in: [selectedService.id]}">
<template slot="list" slot-scope="{data}">
<supplier-pending-order-component :data="data" v-on:input="updateOrder($event)"></supplier-pending-order-component>
</template>
@@ -124,6 +159,14 @@
currencyDropdownLaunch: {
status: false
},
serviceDropdownLaunch: {
status: false
},
selectedService: {
id: 1,
name: '',
status: false
},
payments: []
}
},
@@ -135,6 +178,7 @@
this.suppliers = response.payload.data;
this.updateSupplier(this.suppliers[0]);
this.updateCurrency(this.suppliers[0].currencies[0]);
this.updateService(this.suppliers[0].services[0]);
},
updateSupplier(supplier){
this.selectedSupplier = supplier;
@@ -151,6 +195,10 @@
this.payments = [];
},
updateService(service){
this.selectedService = service;
this.serviceDropdownLaunch.status = false;
},
updateOrder(payment){
this.payments.includes(payment) ? this.payments.splice(this.payments.indexOf(payment), 1) : this.payments.push(payment);
}
@@ -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-balance-component></wallet-balance-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>
@@ -3,7 +3,7 @@
<div class="col">
<div class="row">
<div class="col-12 col-md-10 ">
<div class="row">
<div class="row m-b-20">
<div class="col">
<div class="row">
<div class="col">
@@ -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-balance-component></wallet-balance-component>
<wallet-component :data="company"></wallet-component>
</div>
</div>
</div>
@@ -0,0 +1,141 @@
<template>
<div class="row">
<div class="col">
<loading-component style="height: 200px; top: 0;" key="1" color="success" v-show="isLoading"></loading-component>
<div class="row" v-if="company">
<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-if="company.wallet.length">
<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 d-none">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">{{[5, 9].includes(item.type) ? 'Top Up' : 'Payment to bill'}} </div>
<div class="col-2 text-success">{{[5, 9].includes(item.type) ? (Math.round((item.amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") : ''}}</div>
<div class="col-2 text-danger">{{![5, 9].includes(item.type) ? '- ' + (Math.round((item.amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") : ''}}</div>
<div class="col-2 d-none">Balance</div>
</div>
</div>
</div>
<div class="row align-items-center justify-content-center p-t-50 p-b-50" v-if="!company.wallet.length || !company.wallet[0].transactions.length">
<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-if="company.wallet.length">
<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-if="!company.wallet.length || !company.wallet[0].topup_transactions.length">
<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>
@@ -0,0 +1,75 @@
<template>
<div class="row">
<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">
<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 || 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-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">
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="font-heading fs-8 muted all-caps">Customer Marking</div>
<div class="font-heading fs-10 bold">
Marking & Link
</div>
</div>
</div>
<div class="row">
<div class="col">
<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" :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]">
<template slot="button">
<div class="row align-items-center h-100">
<div class="col">
<i class="fa fa-cloud-download text-white"></i>
</div>
</div>
</template>
</document-file-viewer-component>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import componentHandler from '../../../general/mixins/componentHandler';
export default {
data(){
return {
}
},
mixins: [componentHandler]
}
</script>
@@ -0,0 +1,178 @@
<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">
<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 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 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 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 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 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 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 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>
</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>
</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>
</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>
</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>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import componentHandler from '../../../general/mixins/componentHandler';
import Chart from 'chart.js';
export default {
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
},
{
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'
}
}
},
});
}
},
mixins: [componentHandler]
}
</script>
@@ -0,0 +1,82 @@
<template>
<div class="row">
<div class="col">
<div class="row m-t-15">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.amount">
<label>{{transactionType == 'debit' ? 'Withdraw' : '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-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 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="submitForm()">Confirm</div>
</div>
</div>
</div>
</div>
</template>
<script>
import componentHandler from '../../../general/mixins/componentHandler';
import {VMoney} from 'v-money'
import { required, minValue} from "vuelidate/lib/validators";
export default {
props: {
transactionType:{
type: String,
required: false
}
},
data(){
return {
parameters: {
company_id: this.data,
amount: '0.00',
}
}
},
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){
if (this.transactionType == '') {
window.location.href = 'https://www.billplz-sandbox.com/bills/' + response.payload.data.reference + '?auto_submit=true';
}
},
submitForm() {
if (this.transactionType != '') {
this.submit(this.route('api.wallet.' + this.transactionType), 'post', '', true, true);
return;
}
this.submit(this.route('api.wallet.topup'), 'post', '', true, true);
}
},
mixins: [componentHandler],
directives: {money: VMoney}
}
</script>
@@ -1,121 +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-balance-component></wallet-balance-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-auto btn-rounded bg-master-light d-flex justify-content-center align-content-center">
<div class="padding-5 text-white"><i class="fa fa-check fs-15 lh-40"></i></div>
</div>
<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-auto btn-rounded bg-master-light d-flex justify-content-center align-content-center">
<div class="padding-5 text-white"><i class="fa fa-times fs-15 lh-40"></i></div>
</div>
<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-auto btn-rounded bg-master-light d-flex justify-content-center align-content-center">
<div class="padding-5 text-white"><i class="fa fa-exclamation fs-15 lh-40"></i></div>
</div>
<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>
</div>
</div>
<div class="col">
<customer-transaction-section-component :id="{{$id}}"></customer-transaction-section-component>
</div>
</div>
@@ -0,0 +1,54 @@
@extends('layouts.base_portal')
@section('inner_content')
<div class="row">
<div class="col">
<wallets-component></wallets-component>
<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">
<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>
<wallet-top-up-history-component></wallet-top-up-history-component>
</div>
</div>
</div>
</div>
</div>
</div>
@endsection
+5 -8
View File
@@ -48,6 +48,11 @@
<div class="text-white all-caps fs-12">customers</div>
</a>
</div>
<div class="col-auto p-r-20" v-if="$store.getters.isAdmin">
<a href="{{route('wallet.wallets')}}">
<div class="text-white all-caps fs-12">Wallets</div>
</a>
</div>
<div v-if="$store.getters.isCustomer" class="col-auto p-r-20">
<a href="{{route('banks')}}"><div class="text-white all-caps fs-12">Bank Accounts</div></a>
</div>
@@ -64,14 +69,6 @@
</div>
</div>
</div>
<div class="col-auto m-r-20 d-none d-md-inline hide">
<div class="row align-items-center p-t-5 p-b-5 b-a b-thick" style="border-color: #ffffff3d">
<div class="col-auto">
<div class="fs-12 text-primary-lighter">MYR 0.00</div>
</div>
<top-up-account-component></top-up-account-component>
</div>
</div>
<div class="col-auto m-r-20 d-none d-md-inline">
<div class="row align-items-center p-t-5 p-b-5 b-a b-thick d-inline-flex h-100" style="border-color: #ffffff3d">
<div class="col-auto">
+2 -2
View File
@@ -1,6 +1,6 @@
<div class="row" >
<div class="col">
<div class="row justify-content-center pt-md-0 bg-complete-light">
<div class="row justify-content-center pt-md-0 bg-primary-complete-gradient">
<div class="col p-t-10 p-b-10 p-l-30 p-r-30">
<a href="{{route('dashboard')}}">
<div class="row">
@@ -16,7 +16,7 @@
</a>
</div>
<div class="col-auto d-md-none pointer p-r-25 absolute" @click="$store.dispatch('toggleSection', {name: 'sideMenu', status: false})" style="right: 0;">
<i class="fa fa-times fs-20 m-t-15"></i>
<i class="fa fa-times fs-20 m-t-15 text-white"></i>
</div>
</div>
<div class="row">
+5 -3
View File
@@ -5,8 +5,10 @@ use Illuminate\Support\Facades\Route;
Route::group(['prefix' => 'wallets', 'namespace' => 'Wallets', 'as' => 'wallet.'], function () {
Route::get('/', 'ListWalletController@list')->name('list');
Route::post('/create', 'CreateWalletController@create')->name('create');
Route::post('/topup', 'TopUpWalletController@topUp')->name('topup');
Route::post('/withdraw', 'WithdrawWalletController@withdraw')->name('withdraw');
Route::put('/{transaction_id}/update-status/{status}', 'UpdateStatusWalletController@updateStatus')->where('status', 'approve|reject')->name('approval');
Route::post('/topup', 'TopUpWalletController@topUp')->name('topup'); // user
Route::post('/debit', 'DebitWalletController@debit')->name('debit'); //admin -
Route::post('/credit', 'CreditWalletController@credit')->name('credit'); // admin +
Route::put('/{transaction_id}/update-status/{status}', 'UpdateStatusWalletController@updateStatus')->where('status', 'approve|reject')->name('approval');
});
+26 -4
View File
@@ -1,8 +1,11 @@
<?php
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Booking;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Route;
use Maatwebsite\Excel\Excel;
@@ -76,9 +79,28 @@ Route::get('/transfer/merge/{marking}', function ($marking) {
})->name('booking.merge');
Route::get('/online_payment/redirect', 'Billplz\CallbackBillplzController@callback')->name('online_payment.redirect');
Route::get('/wallet-transactions', function () {
return view('pages.wallet.index');
})->name('wallet.transactions');
Route::get('/export/customers/f614e339d7058904a831aad742e24d55', 'Exports\ExportCustomersToExcelController@export');
Route::get('/export/transactions/f614e339d7058904a831aad742e24d55', 'Exports\ExportCustomersToExcelController@transactions');
Route::get('/products', function (\App\Classes\Modules\Exports\Services\ExportsProducts $exportsProducts) {
return $exportsProducts->download('products.csv', Excel::CSV, ['Content-Type' => 'text/csv']);
})->name('products.random');
//Route::get('/duplicated_bills', function (Request $request) {
// Auth()->login(User::find(1));
// $bookings = Booking::whereIn('id', [10391, 10275, 10109, 10108, 10070, 10066, 10063, 9801, 9166, 8895, 8790, 8544, 8264, 6957, 5409, 4717])->with('transactions')->pluck('marking');
// dd($bookings);
//
//})->name('x2.data');
Route::get('/wallet/{id}/details', function ($id) {
return view('pages.wallet.index', ['id' => $id]);
})->name('wallet.details');
Route::get('/wallets', function () {
return view('pages.wallet.wallets');
})->name('wallet.wallets');
Route::get('/test', function(){
@@ -121,4 +143,4 @@ Route::get('/products', function (\App\Classes\Modules\Exports\Services\ExportsP
return $exportsProducts->download('products.csv', Excel::CSV, ['Content-Type' => 'text/csv']);
})->name('products.random');
Route::get('/auto-purchase-order-fill', 'Bookings\AutoPurchaseOrderFillController@auto')->name('assign');
Route::get('/auto-purchase-order-fill', 'Bookings\AutoPurchaseOrderFillController@auto')->name('assign');