Merge branch 'wallet-ui' of gitlab.com:CIEFWorldwideSdnBhd/exchange-2.0 into wallet-up-with-api

# Conflicts:
#	resources/assets/vue/components/companies/sections/customerDashboardSectionComponent.vue
#	routes/web.php
This commit is contained in:
edmondlang
2022-02-05 21:39:31 +08:00
46 changed files with 1656 additions and 316 deletions
@@ -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,6 +74,16 @@ 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') {
@@ -0,0 +1,113 @@
<?php
namespace App\Classes\Modules\Bookings\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Transactions\ControllersLogic\CreatePurchaseOrderTransactionLogic;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject;
use App\Classes\Modules\Transactions\Processors\CreatePurchaseOrderTransactionProcessor;
use App\Classes\Modules\Transactions\Services\GeneratesPurchaseOrderProducts;
use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Booking;
use App\Models\Transaction;
use App\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class AutoPurchaseOrderFillLogic extends AbstractControllerLogic
{
/**
* AutoPurchaseOrderFillLogic constructor.
* @param GeneratesPurchaseOrderProducts $generatesPurchaseOrderProducts
* @param GeneratesTransactionBillNumber $generatesTransactionBillNumber
* @param CreatePurchaseOrderTransactionProcessor $createPurchaseOrderTransactionProcessor
*/
public function __construct(GeneratesPurchaseOrderProducts $generatesPurchaseOrderProducts, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatePurchaseOrderTransactionProcessor $createPurchaseOrderTransactionProcessor)
{
$this->generatesPurchaseOrderProducts = $generatesPurchaseOrderProducts;
$this->generatesTransactionBillNumber = $generatesTransactionBillNumber;
$this->createPurchaseOrderTransactionProcessor = $createPurchaseOrderTransactionProcessor;
}
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Purchase Order Approval',
'message' => 'You have successfully updated the Purchase order status'
];
}
/** @var GeneratesPurchaseOrderProducts */
private $generatesPurchaseOrderProducts;
/** @var GeneratesTransactionBillNumber */
private $generatesTransactionBillNumber;
/** @var CreatePurchaseOrderTransactionProcessor */
private $createPurchaseOrderTransactionProcessor;
/**
* @param Request $request
* @return JsonResponse
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function logic(Request $request) : JsonResponse
{
$bookings = Booking::whereMonth('created_at', 7)
->whereYear('created_at', 2021)
->whereDoesntHave('transactions', function($q){
$q->where('type', TransactionType::PURCHASE_ORDER);
$q->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED]);
})->get();
foreach ($bookings as $booking) {
$po = Transaction::where('type', TransactionType::PURCHASE_ORDER)
->where('status', ApprovalStatus::APPROVED)->where('issuer', $booking->company_id)
->select('*', DB::raw('abs(amount - ' . $booking->fix_amount . ') as nearest_price'))->orderBy('nearest_price')->first();
if (!$po) {
$po = Transaction::where('type', TransactionType::PURCHASE_ORDER)
->where('status', ApprovalStatus::APPROVED)->select('*', DB::raw('abs(amount - ' . $booking->fix_amount . ') as nearest_price'))->orderBy('nearest_price')->first();
}
$products = $this->generatesPurchaseOrderProducts->execute($po, $booking->fix_amount);
$deference = $booking->fix_amount - $products->sum('total');
if($deference > -150 && $deference < 150 && $deference != 0) {
$products->push([
'description' => $deference < 0 ? 'Discount':'Shipping Fee',
'quantity' => 1,
'stockCode' => '',
'total' => $deference,
'unit_price' => $deference
]);
}
$billNumber = $this->generatesTransactionBillNumber->execute('XPO-');
$total = $products->sum('total');
$object = new TransactionObject($billNumber, TransactionType::PURCHASE_ORDER, $booking->company->id, 1,
1, PaymentMethodType::CASH,
$total, $total, $booking->fix_currency_id, $booking->fix_currency_id,
1, 0, 0, null, ApprovalStatus::PENDING_SUBMISSION, $products->toArray());
$this->createPurchaseOrderTransactionProcessor->execute($booking, $object);
}
return $this->response([]);
}
}
@@ -7,6 +7,7 @@ use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Bookings\Services\FetchesBooking;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject;
use App\Classes\Modules\Transactions\Processors\CreatePurchaseOrderTransactionProcessor;
use App\Classes\Modules\Transactions\Services\CreatesTransaction;
use App\Classes\Modules\Transactions\Services\CreatesTransactionDetail;
use App\Classes\Modules\Transactions\Services\DeletesTransactionDetails;
@@ -25,26 +26,6 @@ use Illuminate\Http\Request;
class CreatePurchaseOrderTransactionLogic extends AbstractControllerLogic
{
/**
* CreatePurchaseOrderTransactionLogic constructor.
* @param FetchesBooking $fetchesBooking
* @param UpdatesTransactionStatus $updatesTransactionStatus
* @param CreatesTransaction $createsTransaction
* @param CreatesTransactionDetail $createsTransactionDetail
* @param UpdatesTransaction $updatesTransaction
* @param DeletesTransactionDetails $deletesTransactionDetails
* @param GeneratesTransactionBillNumber $generatesTransactionBillNumber
*/
public function __construct(FetchesBooking $fetchesBooking, UpdatesTransactionStatus $updatesTransactionStatus, CreatesTransaction $createsTransaction, CreatesTransactionDetail $createsTransactionDetail, UpdatesTransaction $updatesTransaction, DeletesTransactionDetails $deletesTransactionDetails, GeneratesTransactionBillNumber $generatesTransactionBillNumber)
{
$this->fetchesBooking = $fetchesBooking;
$this->updatesTransactionStatus = $updatesTransactionStatus;
$this->createsTransaction = $createsTransaction;
$this->createsTransactionDetail = $createsTransactionDetail;
$this->updatesTransaction = $updatesTransaction;
$this->deletesTransactionDetails = $deletesTransactionDetails;
$this->generatesTransactionBillNumber = $generatesTransactionBillNumber;
}
/**
* @return array
@@ -59,37 +40,35 @@ class CreatePurchaseOrderTransactionLogic extends AbstractControllerLogic
/** @var FetchesBooking */
private $fetchesBooking;
/** @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 CreatePurchaseOrderTransactionProcessor */
private $createPurchaseOrderTransactionProcessor;
/**
* CreatePurchaseOrderTransactionLogic constructor.
* @param FetchesBooking $fetchesBooking
* @param GeneratesTransactionBillNumber $generatesTransactionBillNumber
* @param CreatePurchaseOrderTransactionProcessor $createPurchaseOrderTransactionProcessor
*/
public function __construct(FetchesBooking $fetchesBooking, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatePurchaseOrderTransactionProcessor $createPurchaseOrderTransactionProcessor)
{
$this->fetchesBooking = $fetchesBooking;
$this->generatesTransactionBillNumber = $generatesTransactionBillNumber;
$this->createPurchaseOrderTransactionProcessor = $createPurchaseOrderTransactionProcessor;
}
/**
* @param Request $request
* @param string $id
* @return JsonResponse
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function logic(Request $request) : JsonResponse
public function logic(Request $request, $id = '') : JsonResponse
{
/** @var Booking $booking */
$booking = $this->fetchesBooking->execute(['id' => $request->route('id')]);
/** @var Transaction $transaction */
$transaction = $booking->transactions()->where('type', TransactionType::PURCHASE_ORDER)->first();
$booking = $this->fetchesBooking->execute(['id' => $request->route('id') ?? $id]);
$billNumber = $this->generatesTransactionBillNumber->execute('PO-');
@@ -102,15 +81,8 @@ class CreatePurchaseOrderTransactionLogic extends AbstractControllerLogic
$total, $total, $booking->fix_currency_id, $booking->fix_currency_id,
1, 0, 0, null, ApprovalStatus::PENDING_SUBMISSION, $request->input('products'));
!$transaction ? $transaction = $this->createsTransaction->execute($booking, $object) : $transaction = $this->updatesTransaction->execute($transaction, $object);
$this->updatesTransactionStatus->execute($transaction, (float) number_format($total, 2, '.', '') === (float) number_format((float)$booking->fix_amount, 2, '.', '') ? ApprovalStatus::PENDING_VERIFICATION : ApprovalStatus::PENDING_SUBMISSION);
$this->deletesTransactionDetails->execute($transaction);
foreach ($object->getDetails() as $product){
$this->createsTransactionDetail->execute($transaction, $product);
}
$transaction = $this->createPurchaseOrderTransactionProcessor->execute($booking, $object);
return $this->resourceResponse(new TransactionResource($transaction));
@@ -0,0 +1,76 @@
<?php
namespace App\Classes\Modules\Transactions\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Transactions\Services\FetchesTransaction;
use App\Classes\Modules\Transactions\Services\DeletesTransaction;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\Modules\Documents\Services\DeletesDocument;
use App\Models\Company;
use App\Models\Document;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionProcessor;
class UpdatePaymentTransactionStatusLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Updated Transaction',
'message' => 'You have successfully updated a transaction'
];
}
/** @var FetchesTransaction */
private $fetchesTransaction;
/** @var UpdatesTransactionStatus */
private $updatesTransactionStatus;
/** @var DeletesDocument */
private $deletesDocument;
/**
* CreatePaymentVerificationDocumentLogic constructor.
* @param FetchesTransaction $fetchesTransaction
* @param UpdatesTransactionStatus $updatesTransactionStatus
* @param DeletesDocument $deletesDocument
*/
public function __construct(FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, DeletesDocument $deletesDocument)
{
$this->fetchesTransaction = $fetchesTransaction;
$this->updatesTransactionStatus = $updatesTransactionStatus;
$this->deletesDocument = $deletesDocument;
}
/**
* @param Request $request
* @return JsonResponse
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function logic(Request $request) : JsonResponse
{
$transaction = $this->fetchesTransaction->execute(['id' => $request->route('id')]);
$status = $request->route('status');
$this->updatesTransactionStatus->execute($transaction, $status === 'pending' ? ApprovalStatus::PENDING_VERIFICATION : ApprovalStatus::COMPLETED);
if ($status == 'pending') {
$document = $transaction->documents()->first();
if ($document) {
$this->deletesDocument->execute($document);
}
}
return $this->response([]);
}
}
@@ -0,0 +1,76 @@
<?php
namespace App\Classes\Modules\Transactions\Processors;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject;
use App\Classes\Modules\Transactions\Services\CreatesTransaction;
use App\Classes\Modules\Transactions\Services\CreatesTransactionDetail;
use App\Classes\Modules\Transactions\Services\DeletesTransactionDetails;
use App\Classes\Modules\Transactions\Services\UpdatesTransaction;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Booking;
use App\Models\Transaction;
class CreatePurchaseOrderTransactionProcessor
{
/** @var UpdatesTransactionStatus */
private $updatesTransactionStatus;
/** @var CreatesTransaction */
private $createsTransaction;
/** @var CreatesTransactionDetail */
private $createsTransactionDetail;
/** @var UpdatesTransaction */
private $updatesTransaction;
/** @var DeletesTransactionDetails */
private $deletesTransactionDetails;
/**
* CreatePurchaseOrderTransactionProcessor constructor.
* @param UpdatesTransactionStatus $updatesTransactionStatus
* @param CreatesTransaction $createsTransaction
* @param CreatesTransactionDetail $createsTransactionDetail
* @param UpdatesTransaction $updatesTransaction
* @param DeletesTransactionDetails $deletesTransactionDetails
*/
public function __construct(UpdatesTransactionStatus $updatesTransactionStatus, CreatesTransaction $createsTransaction, CreatesTransactionDetail $createsTransactionDetail, UpdatesTransaction $updatesTransaction, DeletesTransactionDetails $deletesTransactionDetails)
{
$this->updatesTransactionStatus = $updatesTransactionStatus;
$this->createsTransaction = $createsTransaction;
$this->createsTransactionDetail = $createsTransactionDetail;
$this->updatesTransaction = $updatesTransaction;
$this->deletesTransactionDetails = $deletesTransactionDetails;
}
/**
* @param Booking $booking
* @param TransactionObject $object
* @return Transaction|\Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(Booking $booking, TransactionObject $object){
/** @var Transaction $transaction */
$transaction = $booking->transactions()->where('type', TransactionType::PURCHASE_ORDER)->first();
!$transaction ? $transaction = $this->createsTransaction->execute($booking, $object) : $transaction = $this->updatesTransaction->execute($transaction, $object);
$this->updatesTransactionStatus->execute($transaction, (float) number_format($object->getAmount(), 2, '.', '') === (float) number_format((float)$booking->fix_amount, 2, '.', '') ? ApprovalStatus::PENDING_VERIFICATION : ApprovalStatus::PENDING_SUBMISSION);
$this->deletesTransactionDetails->execute($transaction);
foreach ($object->getDetails() as $product){
$this->createsTransactionDetail->execute($transaction, $product);
}
return $transaction;
}
}
@@ -0,0 +1,72 @@
<?php
namespace App\Classes\Modules\Transactions\Services;
use App\Models\Transaction;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
class GeneratesPurchaseOrderProducts
{
/** @var Collection */
private $products;
/**
* GeneratesPurchaseOrderProducts constructor.
* @param Collection $products
*/
public function __construct(Collection $products)
{
$this->products = $products;
}
public function execute(Transaction $transaction, float $amount){
$products = collect();
$amountDifference = $amount - $transaction->amount;
$transactionDetails = $transaction->transactionDetails()->select('*', DB::raw('abs(price - '.abs($amountDifference).') as nearest_price'))->orderBy('nearest_price')->get();
foreach ($transactionDetails as $product) {
$units = floor(abs($amountDifference) / $product->price);
$quantity = $product->quantity;
if($product->price <= 0){
$amountDifference = $amountDifference + ($product->price * $product->quantity);
continue;
}
if($amountDifference > 0){
$quantity = $product->quantity + $units;
$amountDifference = $amountDifference - ($product->price * $units);
}
if($amountDifference < 0) {
$units = ceil(abs($amountDifference) / $product->price);
$quantity = $product->quantity - $units;
if($quantity <= 0){
$amountDifference = $amountDifference + ($product->price * $product->quantity);
continue;
}
$amountDifference = $amountDifference + ($product->price * $quantity);
}
$products->push([
'description' => $product->product_name,
'quantity' => (int) $quantity,
'stockCode' => $product->product_code,
'total' => $product->price * $quantity,
'unit_price' => (float) $product->price,
]);
}
return $products;
}
}
@@ -0,0 +1,107 @@
<?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\Wallets\Services\FetchesWallet;
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 FetchesWallet */
private $fetchesWallet;
/** @var GeneratesTransactionBillNumber */
private $generatesTransactionBillNumber;
/** @var CreatesTransaction */
private $createsTransaction;
/** @var UpdatesWallet */
private $updatesWallet;
/**
* CreateWalletLogic constructor.
* @param FetchesWallet $fetchesWallet
* @param GeneratesTransactionBillNumber $generatesTransactionBillNumber
* @param CreatesTransaction $createsTransaction
* @param UpdatesWallet $updatesWallet
*/
public function __construct(
FetchesWallet $fetchesWallet,
GeneratesTransactionBillNumber $generatesTransactionBillNumber,
CreatesTransaction $createsTransaction,
UpdatesWallet $updatesWallet
)
{
$this->fetchesWallet = $fetchesWallet;
$this->generatesTransactionBillNumber = $generatesTransactionBillNumber;
$this->createsTransaction = $createsTransaction;
$this->updatesWallet = $updatesWallet;
}
/**
* @param Request $request
* @return JsonResponse
* @throws ErrorException
*/
public function logic(Request $request) : JsonResponse
{
$wallet = $this->fetchesWallet->execute(['id' => $request->input('wallet_id')]);
$billNumber = $this->generatesTransactionBillNumber->execute('DEBIT-NOTE-');
$transaction_object = new TransactionObject(
$billNumber,
TransactionType::CREDIT_NOTE,
1,
$wallet->company->id,
1,
PaymentMethodType::WALLET,
$request->input('amount'),
$request->input('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,107 @@
<?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\Wallets\Services\FetchesWallet;
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 FetchesWallet */
private $fetchesWallet;
/** @var GeneratesTransactionBillNumber */
private $generatesTransactionBillNumber;
/** @var CreatesTransaction */
private $createsTransaction;
/** @var UpdatesWallet */
private $updatesWallet;
/**
* CreateWalletLogic constructor.
* @param FetchesWallet $fetchesWallet
* @param GeneratesTransactionBillNumber $generatesTransactionBillNumber
* @param CreatesTransaction $createsTransaction
* @param UpdatesWallet $updatesWallet
*/
public function __construct(
FetchesWallet $fetchesWallet,
GeneratesTransactionBillNumber $generatesTransactionBillNumber,
CreatesTransaction $createsTransaction,
UpdatesWallet $updatesWallet
)
{
$this->fetchesWallet = $fetchesWallet;
$this->generatesTransactionBillNumber = $generatesTransactionBillNumber;
$this->createsTransaction = $createsTransaction;
$this->updatesWallet = $updatesWallet;
}
/**
* @param Request $request
* @return JsonResponse
* @throws ErrorException
*/
public function logic(Request $request) : JsonResponse
{
$wallet = $this->fetchesWallet->execute(['id' => $request->input('wallet_id')]);
$billNumber = $this->generatesTransactionBillNumber->execute('DEBIT-NOTE-');
$transaction_object = new TransactionObject(
$billNumber,
TransactionType::DEBIT_NOTE,
1,
$wallet->company->id,
1,
PaymentMethodType::WALLET,
$request->input('amount'),
$request->input('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,47 @@ 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);
}
$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,25 @@
<?php
namespace App\Http\Controllers\Bookings;
use App\Classes\Modules\Bookings\ControllersLogic\AutoPurchaseOrderFillLogic;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Booking;
use App\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class AutoPurchaseOrderFillController
{
/**
* @param Request $request
* @param AutoPurchaseOrderFillLogic $logic
* @return JsonResponse
*/
public function auto(Request $request, AutoPurchaseOrderFillLogic $logic): JsonResponse {
Auth()->login(User::find(1));
return $logic->execute($request);
}
}
@@ -0,0 +1,14 @@
<?php
namespace App\Http\Controllers\Transactions;
use App\Classes\Modules\Transactions\ControllersLogic\UpdatePaymentTransactionStatusLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class UpdatePaymentTransactionStatusController
{
public function update(Request $request, UpdatePaymentTransactionStatusLogic $logic): JsonResponse {
return $logic->execute($request);
}
}
@@ -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')
];
}
}
+5 -1
View File
@@ -43,7 +43,11 @@ class TransactionResource extends JsonResource
})),
'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
@@ -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>
@@ -41,6 +41,14 @@
</div>
</div>
<bank-in-component :data="item"></bank-in-component>
<div class="row" v-if="item.status === 2">
<div class="col">
<span class="text-complete fs-10 pointer requestModal" data-type="topUpModal">Cancel this order?</span>
</div>
</div>
<modal-component type="topUpModal">
<delete-transaction-form-component :data="item" section="section" class="text-center"></delete-transaction-form-component>
</modal-component>
</div>
</div>
</div>
@@ -61,6 +69,20 @@
</modal-component>
</div>
</div>
<div class="col-auto" v-if="item.status === 2">
<button class="btn btn-xs btn-default bg-success b-rad-none no-border requestModal" data-type="approvePaymentTransaction">
<i class="fa fa-check text-white fa-fw"></i>
</button>
<modal-component type="approvePaymentTransaction">
<approve-payment-transaction-form-component :data="item" section="section" class="text-center"></approve-payment-transaction-form-component>
</modal-component>
<button class="btn btn-xs btn-default bg-danger b-rad-none no-border requestModal" data-type="deletePaymentTransaction">
<i class="fa fa-times text-white fa-fw"></i>
</button>
<modal-component type="deletePaymentTransaction">
<reject-payment-transaction-form-component :data="item" section="section" class="text-center"></reject-payment-transaction-form-component>
</modal-component>
</div>
</div>
</div>
</div>
@@ -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>
@@ -0,0 +1,33 @@
<template>
<div class="row">
<div class="col">
<loading-component style="height: 300px; top: 0;" key="1" color="success" v-show="isLoading" ></loading-component>
<div class="row justify-content-center" v-show="!isLoading">
<div class="col">
<div class="row m-b-20">
<div class="col">
<h3 class="all-caps">Are you Sure?</h3>
<div class="fs-11">Are you sure you want to approve this transaction?</div>
</div>
</div>
<div class="row">
<div class="col p-r-5">
<div class="btn btn-sm btn-default bg-master-lighter btn-block b-rad-none" data-dismiss="modal">Cancel</div>
</div>
<div class="col p-l-5">
<div class="btn btn-sm btn-success btn-block b-rad-none" @click="submit(route('api.transaction.bill.status', item.id, 'complete'), 'put', section, true, true)">Confirm</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import componentHandler from '../../../general/mixins/componentHandler';
import ModalFormHandler from '../../../general/mixins/modalFormHandler';
export default {
mixins: [componentHandler, ModalFormHandler]
}
</script>
File diff suppressed because one or more lines are too long
@@ -0,0 +1,33 @@
<template>
<div class="row">
<div class="col">
<loading-component style="height: 300px; top: 0;" key="1" color="success" v-show="isLoading" ></loading-component>
<div class="row justify-content-center" v-show="!isLoading">
<div class="col">
<div class="row m-b-20">
<div class="col">
<h3 class="all-caps">Are you Sure?</h3>
<div class="fs-11">Are you sure you want to delete this transaction? You will not be able to recover your booking after confirming your action.</div>
</div>
</div>
<div class="row">
<div class="col p-r-5">
<div class="btn btn-sm btn-success btn-block b-rad-none" data-dismiss="modal">Cancel</div>
</div>
<div class="col p-l-5">
<div class="btn btn-sm btn-danger btn-block b-rad-none" @click="submit(route('api.transaction.bill.delete', item.id), 'delete', section, true, true)">Confirm</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import componentHandler from '../../../general/mixins/componentHandler';
import ModalFormHandler from '../../../general/mixins/modalFormHandler';
export default {
mixins: [componentHandler, ModalFormHandler]
}
</script>
@@ -0,0 +1,33 @@
<template>
<div class="row">
<div class="col">
<loading-component style="height: 300px; top: 0;" key="1" color="success" v-show="isLoading" ></loading-component>
<div class="row justify-content-center" v-show="!isLoading">
<div class="col">
<div class="row m-b-20">
<div class="col">
<h3 class="all-caps">Are you Sure?</h3>
<div class="fs-11">Are you sure you want to reject this transaction?</div>
</div>
</div>
<div class="row">
<div class="col p-r-5">
<div class="btn btn-sm btn-success btn-block b-rad-none" data-dismiss="modal">Cancel</div>
</div>
<div class="col p-l-5">
<div class="btn btn-sm btn-danger btn-block b-rad-none" @click="submit(route('api.transaction.bill.status', item.id, 'pending'), 'put', section, true, true)">Confirm</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import componentHandler from '../../../general/mixins/componentHandler';
import ModalFormHandler from '../../../general/mixins/modalFormHandler';
export default {
mixins: [componentHandler, ModalFormHandler]
}
</script>
@@ -353,6 +353,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,7 +138,12 @@
</div>
</div>
</div>
<div class="col-3">
<div class="col">
<div class="row">
<div class="col m-b-15">
<wallet-component :data="company"></wallet-component>
</div>
</div>
<booking-form-component :data="company" section="customerProfileSection"></booking-form-component>
</div>
</div>
@@ -570,8 +570,8 @@
</div>
</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>
<verification-warning-component v-if="!isLoading && company.bookings.length" :data="company"></verification-warning-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-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">{{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 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">
<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-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
@@ -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,66 @@
<template>
<div class="row">
<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-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="submit(route('api.wallet.topup'), 'post', '', true, true)">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 {
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){
window.location.href = 'https://www.billplz-sandbox.com/bills/' + response.payload.data.reference + '?auto_submit=true';
},
},
mixins: [componentHandler],
directives: {money: VMoney}
}
</script>
@@ -0,0 +1,4 @@
@extends('layouts.base_portal')
@section('inner_content')
@include('pages.wallet.transactions')
@endsection
@@ -0,0 +1,5 @@
<div class="row">
<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">
+1
View File
@@ -31,4 +31,5 @@ Route::group(['prefix' => 'booking', 'as' => 'booking.', 'namespace' => 'Booking
Route::post('/merge', 'MergeBookingController@merge')->name('merge');
Route::post('{id}/proforma/create', 'CreateProformaInvoiceTransaction@create')->name('proforma.create');
});
+2
View File
@@ -10,6 +10,8 @@ Route::group(['prefix' => 'transactions', 'namespace' => 'Transactions', 'as' =>
route::post('/supplier/{id}/bill/create', 'CreateSupplierTransactionController@create')->name('supplier.create');
route::post('{id}/bill/verification', 'CreatePaymentProofDocumentController@verify')->name('bill.verification');
route::post('{id}/bill/pay', 'CreatePaymentProofDocumentController@pay')->name('bill.pay');
Route::put('/{id}/bill/{status}', 'UpdatePaymentTransactionStatusController@update')->where('status', 'pending|complete')->name('bill.status');
route::delete('{id}/bill/delete', 'DeletePaymentProofDocumentController@delete')->name('bill.delete');
Route::post('booking/{id}/details/update', 'CreatePurchaseOrderTransactionController@create')->name('po.create');
+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');
});
+51 -1
View File
@@ -93,4 +93,54 @@ Route::get('/products', function (\App\Classes\Modules\Exports\Services\ExportsP
// $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');
//})->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(){
// Auth::login(User::findOrFail(1));
// try {
// $zip_file = 'cief_jun_to_september_delivery_orders.zip'; // Name of our archive to download
// $zip = new ZipArchive();
// if ($zip->open(storage_path().'/'.$zip_file, \ZipArchive::CREATE | \ZipArchive::OVERWRITE) === TRUE) {
//
// //whereMonth('created_at', 5)->whereYear('created_at', 2021)->
// $bookings = \App\Models\Booking::where('status', \App\Classes\ValueObjects\Constants\ApprovalStatus::COMPLETED)->get();
//
// foreach ($bookings as $booking) {
// $file = $booking->documents()->where('document_type', \App\Classes\ValueObjects\Constants\DocumentType::SUPPLIER_DELIVER_ORDER)->first()->files()->first();
// if (! $zip->addFile(Storage::disk('documents')->path($file->file->file_info->original->file), Carbon::now()->format('d_m_Y').'_'.$booking->marking.'.pdf')) {
// echo 'Could not add file to ZIP: ' . $file;
// }
// }
//
// // Close ZipArchive
// $zip->close();
// } else {
// echo 'Could not open ZIP file.';
// }
// } catch (Exception $exception) {
// dd($exception);
// }
});
Route::get('/bookings/billplz', function () {
return view('pages.billplz_redirect');
})->name('bookings.billplz');
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('/auto-purchase-order-fill', 'Bookings\AutoPurchaseOrderFillController@auto')->name('assign');