Merge branch 'development' into 'master'

update PaymentProofComponent - add in function to delete transaction on...

See merge request CIEFWorldwideSdnBhd/exchange-2.0!79
This commit is contained in:
omair saleh
2022-02-21 16:44:37 +00:00
85 changed files with 3741 additions and 1805 deletions
@@ -6,6 +6,7 @@ namespace App\Classes\General\Eloquent;
use App\Classes\Exceptions\ResourceNotFoundException;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Psy\Exception\ErrorException;
abstract class AbstractFetchRecord extends AbstractGetRecord
{
@@ -0,0 +1,23 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use App\Models\Booking;
use Illuminate\Database\Eloquent\Builder;
class TransactionServiceId implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('owner_type', Booking::class)->whereHas('booking', function ($query) use($value) {
$query->where('service_id', $value);
});
}
}
@@ -2,10 +2,15 @@
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\Classes\Modules\Wallets\Services\UpdatesWalletBalance;
use App\Http\Resources\TransactionResource;
use App\Models\Booking;
use App\Models\User;
use App\Models\Wallet;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
@@ -32,18 +37,22 @@ class CallbackBillplzLogic
/** @var UpdatesTransactionStatus */
private $updatesTransactionStatus;
/** @var UpdatesWalletBalance */
private $updatesWalletBalance;
/**
* CreateBookingLogic constructor.
* CallbackBillplzLogic constructor.
* @param GetBillplzBill $getBillplzBill
* @param FetchesTransaction $fetchesTransaction
* @param UpdatesTransactionStatus $updatesTransactionStatus
* @param UpdatesWalletBalance $updatesWalletBalance
*/
public function __construct(GetBillplzBill $getBillplzBill, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus)
public function __construct(GetBillplzBill $getBillplzBill, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, UpdatesWalletBalance $updatesWalletBalance)
{
$this->getBillplzBill = $getBillplzBill;
$this->fetchesTransaction = $fetchesTransaction;
$this->updatesTransactionStatus = $updatesTransactionStatus;
$this->updatesWalletBalance = $updatesWalletBalance;
}
@@ -55,7 +64,6 @@ class CallbackBillplzLogic
*/
public function execute(Request $request)
{
$billplzXSignatureObject = new BillplzXSignatureObject($request);
if(!$billplzXSignatureObject->isValidSignature()){
@@ -77,14 +85,21 @@ class CallbackBillplzLogic
}
if($transaction->status !== ApprovalStatus::COMPLETED){
if($transaction->owner instanceof Wallet && $transaction->status !== ApprovalStatus::APPROVED && $status === ApprovalStatus::APPROVED) {
$this->updatesWalletBalance->execute($transaction->owner, $transaction->amount);
}
$this->updatesTransactionStatus->execute($transaction, $status);
}
$token = Auth::fromUser(User::find(1));
$request->headers->set('Authorization', 'Bearer '.$token);
return $request->method() === 'POST' ? true : view('pages.payments_redirect', ['marking' => $transaction->booking->marking, 'payment_reference' => $transaction->payment_reference, 'status' => $status, 'amount' => $transaction->amount]);
$marking = $transaction->owner instanceof Booking ? $transaction->booking->marking : $transaction->owner->owner->bookings()->orderBy('id', 'DESC')->first()->marking;
return $request->method() === 'POST' ? true : view('pages.payments_redirect', ['marking' => $marking, 'transaction' => $transaction, 'status' => $status]);
}
}
@@ -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([]);
}
}
@@ -14,11 +14,15 @@ use App\Classes\Modules\Transactions\Services\CreatesTransaction;
use App\Classes\Modules\Transactions\Services\UpdatesTransaction;
use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber;
use App\Classes\Modules\Billplzs\Services\CreatesBillplzBill;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\Modules\Wallets\Services\UpdatesWalletBalance;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Http\Resources\TransactionResource;
use App\Models\Booking;
use App\Models\Transaction;
use App\Models\Wallet;
use Carbon\Carbon;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -48,15 +52,18 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic
/** @var CreatesTransaction */
private $createsTransaction;
/** @var UpdatesTransaction */
private $updatesTransaction;
/** @var CalculatesBookingOutstanding */
private $calculatesBookingOutstanding;
/** @var CreatesBillplzBill */
private $createsBillplzBill;
/** @var UpdatesWalletBalance */
private $updatesWalletBalance;
/** @var UpdatesTransactionStatus */
private $updatesTransactionStatus;
/**
* CreateBookingPaymentLogic constructor.
* @param FetchesBookingQuotation $fetchBookingQuotation
@@ -65,16 +72,19 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic
* @param CreatesTransaction $createsTransaction
* @param CalculatesBookingOutstanding $calculatesBookingOutstanding
* @param CreatesBillplzBill $createsBillplzBill
* @param UpdatesWalletBalance $updatesWalletBalance
* @param UpdatesTransactionStatus $updatesTransactionStatus
*/
public function __construct(FetchesBookingQuotation $fetchBookingQuotation, FetchesCompanyPaymentAttemptLimit $fetchesCompanyPaymentAttemptLimit, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatesTransaction $createsTransaction, UpdatesTransaction $updatesTransaction, CalculatesBookingOutstanding $calculatesBookingOutstanding, CreatesBillplzBill $createsBillplzBill)
public function __construct(FetchesBookingQuotation $fetchBookingQuotation, FetchesCompanyPaymentAttemptLimit $fetchesCompanyPaymentAttemptLimit, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatesTransaction $createsTransaction, CalculatesBookingOutstanding $calculatesBookingOutstanding, CreatesBillplzBill $createsBillplzBill, UpdatesWalletBalance $updatesWalletBalance, UpdatesTransactionStatus $updatesTransactionStatus)
{
$this->fetchBookingQuotation = $fetchBookingQuotation;
$this->fetchesCompanyPaymentAttemptLimit = $fetchesCompanyPaymentAttemptLimit;
$this->generatesTransactionBillNumber = $generatesTransactionBillNumber;
$this->createsTransaction = $createsTransaction;
$this->updatesTransaction = $updatesTransaction;
$this->calculatesBookingOutstanding = $calculatesBookingOutstanding;
$this->createsBillplzBill = $createsBillplzBill;
$this->updatesWalletBalance = $updatesWalletBalance;
$this->updatesTransactionStatus = $updatesTransactionStatus;
}
/**
@@ -98,18 +108,47 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic
$billNumber = $this->generatesTransactionBillNumber->execute('PYMT-');
$paymentReference = null;
$amount = $configurations->getTotal();
if(PaymentMethodType::PAYMENT_METHODS[$request->input('payment_method')] == PaymentMethodType::PAYMENT_GATEWAY){
$billPlzBill = $this->createsBillplzBill->execute($request->user()->name, $request->user()->email, 'This payment is made for transfer ref. '.$booking->marking, $configurations->getTotal(), $billNumber, $request->input('bank_code'));
$paymentReference = $billPlzBill->id;
}
if(PaymentMethodType::PAYMENT_METHODS[$request->input('payment_method')] == PaymentMethodType::WALLET){
/** @var Wallet $wallet */
$wallet = $booking->company->wallets()->first();
if($wallet->amount < $amount){
throw new MalformedRequestException('Insufficient wallet balance. Please Top up your wallet.');
}
$transaction_object = new TransactionObject($billNumber, TransactionType::PAYMENT, 1, $booking->company->id, 1, PaymentMethodType::WALLET, $amount, $amount, 1, 1, 1, 0, 0, null, ApprovalStatus::APPROVED, [], '');
$this->createsTransaction->execute($wallet, $transaction_object);
$paymentReference = $billNumber;
$this->updatesWalletBalance->execute($wallet, ($amount * -1));
}
$billNumber = $this->generatesTransactionBillNumber->execute('PYMT-');
$object = new TransactionObject($billNumber, TransactionType::PAYMENT, 1, $booking->company->id,
$configurations->getConfigurations()->getBankId(), $configurations->getConversionObject()->getPaymentMethod(),
$configurations->getTotal(), $configurations->getForeignTotal(), 1,
$configurations->getConversionObject()->getCurrencyId(), $configurations->getConfigurations()->getRate(),
$configurations->getTax(), $configurations->getServiceCharge(), Carbon::now()->addMinutes($paymentAttemptLimit), ApprovalStatus::PENDING_SUBMISSION, [], isset($billPlzBill) ? $billPlzBill->id : NULL);
$configurations->getTax(), $configurations->getServiceCharge(), Carbon::now()->addMinutes($paymentAttemptLimit), ApprovalStatus::PENDING_SUBMISSION, [], $paymentReference);
/** @var Transaction $transaction */
$transaction = $this->createsTransaction->execute($booking, $object);
if(PaymentMethodType::PAYMENT_METHODS[$request->input('payment_method')] == PaymentMethodType::WALLET){
$this->updatesTransactionStatus->execute($transaction, ApprovalStatus::APPROVED);
}
return $this->resourceResponse(new TransactionResource($transaction));
}
@@ -56,23 +56,15 @@ class UpdateCompanyLogic extends AbstractControllerLogic
*/
public function logic(Request $request) : JsonResponse
{
try {
$object = new CompanyObject($request->input('name'), $request->input('reference'), $request->input('type'));
$object = new CompanyObject($request->input('reference_no'), $request->input('name'), $request->input('type'));
$this->canUpdateCompany->passes($object);
$this->canUpdateCompany->passes($object);
$query = $this->fetchesCompany->execute(['id' => $request->route('id')]);
$query = $this->fetchesCompany->execute(['id' => $request->route('id')]);
$query = $this->updatesCompany->execute($query, $object);
return $this->resourceResponse(new CompanyResource($query));
} catch (\Exception $exception){
throw new ErrorException($exception->getMessage(), $exception->getCode());
}
$query = $this->updatesCompany->execute($query, $object);
return $this->resourceResponse(new CompanyResource($query));
}
}
@@ -0,0 +1,70 @@
<?php
namespace App\Classes\Modules\Documents\ControllersLogic;
use App\Classes\Modules\Documents\Standards\Rules\CanDeleteDocument;
use App\Http\Resources\DocumentResource;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Documents\Services\FetchesDocument;
use App\Classes\Modules\Documents\Services\DeletesDocument;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionProcessor;
class DeleteDocumentLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Deleted Document',
'message' => 'You have successfully deleted a document'
];
}
/** @var FetchesDocument */
private $fetchesDocument;
/** @var DeletesDocument */
private $deletesDocument;
/** @var CanDeleteDocument */
private $canDeleteDocument;
/**
* DeleteDocumentLogic constructor.
* @param FetchesDocument $fetchesDocument
* @param DeletesDocument $deletesDocument
* @param CanDeleteDocument $canDeleteDocument
*/
public function __construct(FetchesDocument $fetchesDocument, DeletesDocument $deletesDocument, CanDeleteDocument $canDeleteDocument)
{
$this->fetchesDocument = $fetchesDocument;
$this->deletesDocument = $deletesDocument;
$this->canDeleteDocument = $canDeleteDocument;
}
/**
* @param Request $request
* @return JsonResponse
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function logic(Request $request) : JsonResponse
{
$document = $this->fetchesDocument->execute(['id' => $request->route('id')]);
$this->canDeleteDocument->passes();
$this->deletesDocument->execute($document);
return $this->response([]);
}
}
@@ -0,0 +1,68 @@
<?php
namespace App\Classes\Modules\Documents\ControllersLogic;
use App\Classes\Modules\Documents\Standards\Rules\CanUpdateDocumentReference;
use App\Http\Resources\DocumentResource;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Documents\Services\FetchesDocument;
use App\Classes\Modules\Documents\Services\UpdatesDocumentReference;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class UpdateDocumentReferenceLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Update Document',
'message' => 'You have successfully updated the Document'
];
}
/** @var CanUpdateDocumentReference*/
private $canUpdateDocumentReference;
/** @var UpdatesDocumentReference */
private $updatesDocumentReference;
/** @var FetchesDocument */
private $fetchesDocument;
/**
* RejectDocumentLogic constructor.
* @param CanApproveDocument $canApproveDocument
* @param ApprovesDocument $approvesDocument
* @param FetchesDocument $fetchesDocument
*/
public function __construct(CanUpdateDocumentReference $canUpdateDocumentReference, UpdatesDocumentReference $updatesDocumentReference, FetchesDocument $fetchesDocument)
{
$this->canUpdateDocumentReference = $canUpdateDocumentReference;
$this->updatesDocumentReference = $updatesDocumentReference;
$this->fetchesDocument = $fetchesDocument;
}
/**
* @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
{
$document = $this->fetchesDocument->execute(['id' => $request->route('id')]);
$this->canUpdateDocumentReference->passes();
$document_query = $this->updatesDocumentReference->execute($document, $request->input('identification_number'));
return $this->resourceResponse(new DocumentResource($document_query));
}
}
@@ -0,0 +1,19 @@
<?php
namespace App\Classes\Modules\Documents\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Models\Document;
class UpdatesDocument extends AbstractUpdateRecord
{
/**
* @param Document $model
* @return mixed
*/
public function execute(Document $model) {
return $this->handler($model);
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\Modules\Documents\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Models\Document;
class UpdatesDocumentReference extends AbstractUpdateRecord
{
/**
* @param Document $model
* @return mixed
*/
public function execute(Document $model, string $reference) {
$model->reference = $reference;
return $this->handler($model);
}
}
@@ -0,0 +1,39 @@
<?php
namespace App\Classes\Modules\Documents\Standards\Rules;
use App\Classes\General\Abstracts\AbstractRule;
class CanDeleteDocument extends AbstractRule
{
/**
* @return bool
*/
protected function authorized(): bool
{
// TODO Set Authorization rules
return true;
}
/**
* @param $object
* @return bool
*/
protected function validators($object): bool
{
return true;
}
/**
* @param $object
* @return bool
*/
protected function criteria($object): bool
{
return true;
}
}
@@ -0,0 +1,39 @@
<?php
namespace App\Classes\Modules\Documents\Standards\Rules;
use App\Classes\General\Abstracts\AbstractRule;
use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject;
class CanUpdateDocumentReference extends AbstractRule
{
/**
* @return bool
*/
protected function authorized(): bool
{
// TODO Set Authorization rules
return true;
}
/**
* @param DocumentObject $object
* @return bool
* @throws \App\Classes\Exceptions\RequestValidationException
*/
protected function validators($object): bool
{
return true;
}
/**
* @param DocumentObject $object
* @return bool
*/
protected function criteria($object): bool
{
return true;
}
}
@@ -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));
@@ -91,6 +91,7 @@ class CreateSupplierTransactionLogic extends AbstractControllerLogic
public function logic(Request $request) : JsonResponse
{
$supplier = $this->fetchesCompany->execute(['id' => $request->route('id')]);
$rate = $request->input('rate');
@@ -111,7 +112,7 @@ class CreateSupplierTransactionLogic extends AbstractControllerLogic
$payment->original_amount * (1 / $rate), $payment->original_amount, 1, $payment->original_currency_id,
$rate, 0, 0, null, ApprovalStatus::PENDING_VERIFICATION);
$transactions[] = $this->createsTransaction->execute($payment->booking, $object);
$transactions[] = $this->createsTransaction->execute($payment, $object);
}
if(!count($transactions)) return $this->response([]);
@@ -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,117 @@
<?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 \App\Classes\Exceptions\MalformedRequestException
*/
public function logic(Request $request) : JsonResponse
{
$amount = floatval(str_replace(',', '', $request->input('amount')));
$company = $this->fetchesCompany->execute(['id' => $request->input('company_id')]);
$reference = $request->input('reference');
$type = $request->input('transaction_type');
if (!$company->wallets()->first()) {
$object = new WalletObject($company->id, 1, $this->generatesWalletCode->execute());
$this->createsWallet->execute($object, $company);
}
$wallet = $company->wallets()->first();
$billNumber = $this->generatesTransactionBillNumber->execute($type === 2 ? 'DEBIT-NOTE-' : 'CREDIT-NOTE-');
$transaction_object = new TransactionObject($billNumber, $type === 2 ? TransactionType::DEBIT_NOTE : TransactionType::CREDIT_NOTE, 1, $wallet->company->id, 1, PaymentMethodType::CASH, $amount, $amount, 1, 1, 1, 0, 0, null, ApprovalStatus::APPROVED, [], $reference);
$transaction = $this->createsTransaction->execute($wallet, $transaction_object);
$updateWalletAmount = $type === 2 ? ($wallet->amount - $transaction->amount) : ($wallet->amount + $transaction->amount);
$walletObject = new WalletObject($wallet->company->id, $wallet->currency_id, $wallet->code, $updateWalletAmount);
$wallet = $this->updatesWallet->execute($wallet, $walletObject);
return $this->resourceResponse(new WalletResource($wallet));
}
}
@@ -0,0 +1,117 @@
<?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 \App\Classes\Exceptions\MalformedRequestException
*/
public function logic(Request $request) : JsonResponse
{
$amount = floatval(str_replace(',', '', $request->input('amount')));
$company = $this->fetchesCompany->execute(['id' => $request->input('company_id')]);
$reference = $request->input('reference');
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::CASH,
$amount,
$amount,
1,
1,
1,
0,
0,
null,
ApprovalStatus::APPROVED,
[],
$reference
);
$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));
}
}
@@ -2,17 +2,23 @@
namespace App\Classes\Modules\Wallets\ControllersLogic;
use App\Classes\Exceptions\MalformedRequestException;
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\CreatesWalletTransaction;
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 App\Models\Wallet;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -20,53 +26,88 @@ use Illuminate\Support\Facades\DB;
class TopUpWalletLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'TopUp into Company Wallet',
'message' => 'You have successfully topup company wallet'
'message' => 'You have successfully created a topup request for company\'s wallet'
];
}
/** @var FetchesWallet */
private $fetchesWallet;
/** @var CanTopUpWallet */
private $canTopUpWallet;
/** @var FetchesCompany */
private $fetchesCompany;
/** @var GeneratesWalletCode */
private $generatesWalletCode;
/** @var CreatesWallet */
private $createsWallet;
/** @var GeneratesTransactionBillNumber */
private $generatesTransactionBillNumber;
/** @var CreatesBillplzBill */
private $createsBillplzBill;
/** @var CreatesTransaction */
private $createsTransaction;
/** @var CreateWalletTransactionProcessor */
private $createWalletTransactionProcessor;
/**
* CreateWalletLogic constructor.
* @param CreatesWallet $createsWallet
* TopUpWalletLogic constructor.
* @param FetchesCompany $fetchesCompany
* @param GeneratesWalletCode $generatesWalletCode
* @param CanCreateCompanyWallet $canCreateCompanyWallet
* @param CreatesWallet $createsWallet
* @param GeneratesTransactionBillNumber $generatesTransactionBillNumber
* @param CreatesBillplzBill $createsBillplzBill
* @param CreatesTransaction $createsTransaction
*/
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;
}
/**
* @param Request $request
* @return JsonResponse
* @throws ErrorException
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
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')]);
$walletOject = new WalletObject( $wallet->company->id, $wallet->currency_id, $wallet->code, $request->input('amount'));
/** @var Wallet $wallet */
$wallet = $company->wallets()->first();
$this->canTopUpWallet->passes($walletOject);
if (!$wallet) {
$object = new WalletObject($company->id, 1, $this->generatesWalletCode->execute());
/** @var Wallet $wallet */
$wallet = $this->createsWallet->execute($object, $company);
}
$transaction = $this->createWalletTransactionProcessor->execute($wallet, $walletOject, TransactionType::TOP_UP);
$user = $company->employees()->first();
$billNumber = $this->generatesTransactionBillNumber->execute('TOPUP-');
return $this->resourceResponse(new WalletResource($wallet));
if($amount < 0) {
throw new MalformedRequestException('Top up credit value must be greater than zero.');
}
$billPlzBill = $this->createsBillplzBill->execute($user->name, $user->email, 'This payment is credit topup for company ref. ' . $company->reference, $amount, $billNumber, $request->input('bank_code'));
$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->createsTransaction->execute($wallet, $transaction_object);
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);
}
}
@@ -0,0 +1,25 @@
<?php
namespace App\Classes\Modules\Wallets\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Classes\General\Eloquent\AbstractUpdateRelationshipRecord;
use App\Classes\Modules\Wallets\DataTransferObjects\WalletObject;
use App\Models\Wallet;
use App\Models\Company;
class UpdatesWalletBalance extends AbstractUpdateRecord
{
/**
* @param Wallet $model
* @param $amount
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(Wallet $model, $amount) {
$model->amount = $model->amount + $amount;
return $this->handler($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);
}
}
@@ -2,7 +2,7 @@
namespace App\Http\Controllers\Documents;
use App\Classes\Modules\Documents\ControllersLogic\ApproveIdentificationDocumentLogic;
use App\Classes\Modules\Documents\ControllersLogic\ApproveDocumentLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -13,7 +13,7 @@ class ApproveDocumentController
* @param ApproveIdentificationDocumentLogic $logic
* @return JsonResponse
*/
public function approve(Request $request, ApproveIdentificationDocumentLogic $logic): JsonResponse {
public function approve(Request $request, ApproveDocumentLogic $logic): JsonResponse {
return $logic->execute($request);
}
@@ -0,0 +1,14 @@
<?php
namespace App\Http\Controllers\Documents;
use App\Classes\Modules\Documents\ControllersLogic\DeleteDocumentLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class DeleteDocumentController
{
public function delete(Request $request, DeleteDocumentLogic $logic): JsonResponse {
return $logic->execute($request);
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Http\Controllers\Documents;
use App\Classes\Modules\Documents\ControllersLogic\UpdateDocumentReferenceLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class UpdateDocumentReferenceController
{
/**
* @param Request $request
* @param UpdateDocumentReferenceLogic $logic
* @return JsonResponse
*/
public function update(Request $request, UpdateDocumentReferenceLogic $logic): JsonResponse {
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 -5
View File
@@ -57,11 +57,7 @@ class BookingResource extends JsonResource
'expired_payment_attempts' => TransactionResource::collection($this->transactions()->payments()->where('status', ApprovalStatus::PENDING_SUBMISSION)->whereDate('expires_on', '<', Carbon::now())->get()),
'payment_history' => TransactionResource::collection($this->transactions()->where(function($query){
$query->where(function($query){
$query->where(function($query){
$query->payments()->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::REJECTED]);
})->orWhere(function($query){
$query->where('type', TransactionType::BILL)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]);
});
$query->payments();
})->orWhere(function($query){
$query->where(function($query){
$query->where('type', TransactionType::REFUND)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::REJECTED, ApprovalStatus::COMPLETED]);
+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' => new WalletResource($this->wallets()->first()),
'created_at' => $this->created_at->format('d-m-Y')
];
}
}
+7 -8
View File
@@ -35,15 +35,14 @@ 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, 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();
})),
// 'transaction_payment' => new TransactionResource($this->when((int) $this->type === TransactionType::BILL, $this->owner)),
'transaction_bill' => new TransactionResource($this->when((int) $this->type === TransactionType::PAYMENT, $this->transactions()->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'),
]
];
}
}
+4 -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,9 @@ 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' => WalletTransactionResource::collection($this->transactions()->whereIn('status', [2, 3])->orderBy('id', 'DESC')->get()),
'top_up_records' => WalletTransactionResource::collection($this->transactions()->whereNotIn('status', [0])->where('type', TransactionType::TOP_UP)->orderBy('id', 'DESC')->get())
];
}
}
@@ -2,6 +2,10 @@
namespace App\Http\Resources;
use App\Classes\General\Eloquent\Filters\TransactionServiceId;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Transaction;
use Carbon\Carbon;
use Illuminate\Http\Resources\Json\JsonResource;
class WalletTransactionResource extends JsonResource
@@ -14,16 +18,38 @@ class WalletTransactionResource extends JsonResource
*/
public function toArray($request)
{
$description = '';
switch((int) $this->type){
case 5:
$description = (double) $this->amount.' Credit Top up';
break;
case 9:
$description = 'Credit Voucher for '.$this->payment_reference;
break;
case 1:
$marking = Transaction::where('payment_reference', $this->bill_no)->first()->owner->marking;
$description = 'Payment For booking refs.'.'<a href="'.route('booking.details', $marking).'">'.$marking.'</a>';
break;
case 11:
$description = 'Debit Voucher for '.$this->payment_reference;
break;
}
return [
'id' => $this->id,
'wallet_id' => (int) $this->wallet_id,
'bill_no' => (int) $this->bill_no,
'trans_type'=>(int) $this->trans_type,
'type' => (int) $this->type,
'bill_no' => $this->bill_no,
'reference' => $this->payment_reference,
'payment_method' => (float) $this->payment_method,
'issuer_name' => $this->issuerCompany->name,
'amount' => (double) $this->amount,
'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
'service_charge' => (double) $this->service_charge,
'tax' => (double) $this->tax,
'status' => (int) $this->status,
'description' => $description,
'details' => TransactionDetailResource::collection($this->transactionDetails),
'updated_at' => Carbon::parse($this->updated_at)->format('d-m-Y h:i:s A'),
'created_at' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A')
];
}
}
+4 -2
View File
@@ -96,8 +96,10 @@ class Booking extends AbstractModel implements Documentable, Transactionable
protected static function booted()
{
if (auth()->user()->type === RoleTypes::USER) {
static::addGlobalScope(new CustomerBookingsScope);
if (auth()->user()) {
if (auth()->user()->type === RoleTypes::USER) {
static::addGlobalScope(new CustomerBookingsScope);
}
}
}
+5 -12
View File
@@ -3,6 +3,7 @@
namespace App\Models;
use App\Classes\General\Interfaces\Documentable;
use App\Classes\General\Interfaces\Transactionable;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use Carbon\Carbon;
@@ -16,7 +17,7 @@ use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\Relations\MorphTo;
class Transaction extends AbstractModel implements Documentable
class Transaction extends AbstractModel implements Documentable, Transactionable
{
use SoftDeletes;
@@ -35,20 +36,12 @@ class Transaction extends AbstractModel implements Documentable
return $this->BelongsTo(Booking::class, 'owner_id', 'id');
}
/**
/**
* @return MorphMany
*/
public function wallets(): morphMany
public function transactions(): MorphMany
{
return $this->morphMany(Wallet::class, 'owner');
}
/**
* @return BelongsTo
*/
public function wallet(): BelongsTo
{
return $this->BelongsTo(Wallet::class, 'owner_id', 'id');
return $this->MorphMany(Transaction::class, 'owner');
}
/**
+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;
@@ -0,0 +1,35 @@
<?php
use App\Models\Transaction;
use App\Classes\ValueObjects\Constants\TransactionType;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class UpdateTransactionBillOwnerSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
DB::beginTransaction();
$transaction = Transaction::where('type', TransactionType::BILL)->get();
foreach ($transaction as $key => $row) {
$key = 0;
$bills = $row->booking->transactions()->bills()->where('original_amount', '=', $row->original_amount)->get();
if(count($bills) > 1){ $key = $bills->search(function($bill)use($row){ return $bill->id === $row->id; }); }
$paymentTransaction = $row->booking->transactions()->payments()->complete()->where('original_amount', '=', $row->original_amount)->skip($key)->first();
$row->owner_type = Transaction::class;
$row->owner_id = $paymentTransaction->id;
$row->update();
}
DB::commit();
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

@@ -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>
@@ -1,22 +1,9 @@
<template>
<div class="row zig-zag-top">
<div class="col bg-white padding-25">
<div class="row p-b-20 b-b b-dashed m-b-20 b-grey" v-if="defaultAddress[0]">
<div class="row">
<div class="col">
<div class="row m-b-15" v-if="defaultAddress">
<div class="col">
<div class="row m-b-5">
<div class="col">
<div class="font-heading all-caps bold fs-10">Default Billing Address</div>
<div class="font-heading fs-10">
{{defaultAddress[0].street_one}} {{defaultAddress[0].street_two}}, {{defaultAddress[0].district.name}}, {{defaultAddress[0].post_code}} {{defaultAddress[0].state.name}}, {{defaultAddress[0].country.name}}
</div>
</div>
</div>
</div>
</div>
<div class="row p-b-20 b-b b-dashed b-grey m-b-20">
<div class="col">
<div class="row">
<div class="row" v-if="!createAddress">
<div class="col">
<div class="row m-b-10" v-if="billingAddress.length > 0">
<div class="col">
@@ -24,7 +11,7 @@
<div class="col-auto p-l-0">
<div class="row align-items-center justify-content-center">
<div class="col-auto">
<div class="fs-10 all-caps">List of Address </div>
<div class="font-heading fs-10 muted all-caps">Address Book</div>
</div>
<div class="col-auto text-right lh-10 p-r-0 p-l-0 hide">
<i class="fa fa-info-circle fs-10 lh-15 hint-text"></i>
@@ -33,20 +20,15 @@
</div>
</div>
<div class="row">
<div class="col-8">
<div class="col">
<div class="row">
<div class="col p-r-0">
<div class="col">
<div class="btn btn-xs btn-default bg-transparent text-master btn-block text-left b-rad-none p-t-0 p-b-0 p-l-15 p-r-15" @click="addressDropdownLaunch.status = !addressDropdownLaunch.status">
<div class="row">
<div class="col p-t-10 p-b-5 ">
<div class="row">
<div class="col">
<div class="font-heading bold lh-15">{{selectedAddress.street_one}}{{selectedAddress.street_two ? ', ': ''}}{{selectedAddress.street_two}}</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="font-heading all-caps fs-10 muted"><b class="m-r-5 text-primary">{{selectedAddress.post_code}}</b> {{selectedAddress.district.name}}</div>
<div class="font-heading bold lh-15">{{selectedAddress.street_one}}{{selectedAddress.street_two}}, {{selectedAddress.district.name}} {{selectedAddress.post_code}} {{selectedAddress.state.name}}, {{selectedAddress.country.name}}</div>
</div>
</div>
</div>
@@ -69,13 +51,7 @@
<div class="col">
<div class="row">
<div class="col">
<!-- <div class="font-heading bold lh-15 fs-10">{{address.post_code ? address.post_code + ' - ':''}}{{address.post_code}}</div> -->
<div class="font-heading bold lh-15 fs-10">{{address.street_one}}{{selectedAddress.street_two ? ', ': ''}}{{address.street_two}}</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="font-heading all-caps fs-10 muted"><b class="m-r-5 text-primary">{{address.post_code}}</b> {{address.district.name}}</div>
<div class="font-heading bold lh-15 fs-10">{{address.street_one}} {{address.street_two}}, {{address.district.name}} {{address.post_code}} {{address.state.name}}, {{address.country.name}}</div>
</div>
</div>
</div>
@@ -106,16 +82,19 @@
</div>
<div class="row" v-show="createAddress">
<div class="col">
<div>Address form</div>
<address-form-component :id="company_id" :type="2" v-on:createdAddress="updateAddress($event)" v-on:close="createAddress = !createAddress"></address-form-component>
<p class="link text-complete text-underline pointer text-center" @click="createAddress = false">Select from address book</p>
</div>
</div>
</div>
</div>
</div>
</div>
<set-default-billing-address-component :section="section" :data="item" v-if="item.id != null && defaultAddress[0].id != item.id" v-on:updateBillingAddress="updateBillingAddress($event)"></set-default-billing-address-component>
<div class="row" v-if="selectedAddress">
<div class="col">
<set-default-billing-address-component :section="section" :data="selectedAddress" v-if="selectedAddress.id !== defaultAddress.id" v-on:updateBillingAddress="updateBillingAddress($event)"></set-default-billing-address-component>
</div>
</div>
</div>
</div>
@@ -140,9 +119,6 @@
status: false
},
selectedAddress: null,
item:{
id:null
}
}
},
computed: {
@@ -151,13 +127,14 @@
},
defaultAddress: function() {
let defaultAddress = this.billingAddress.filter(function(item) {
return item.billing == 1;
return item.billing === 1;
});
if(!this.selectedAddress){
this.selectedAddress = defaultAddress[0];
}
return defaultAddress;
}
return defaultAddress[0];
},
},
watch: {
pendingQueue(inComplete){
@@ -176,15 +153,11 @@
successHandler(response){
this.billingAddress = response.payload.data;
},
errorHandler(){
// window.location.href = this.route('dashboard')
},
updateAddress(address){
console.log(address);
this.addressDropdownLaunch.status = false;
this.selectedAddress = address;
this.createAddress = false;
this.fetchBillingAddress();
this.item.id = address.id;
},
updateBillingAddress(address){
this.id = address;
@@ -1,46 +1,78 @@
<template>
<div class="row p-t-25 text-left">
<div class="col">
<div class="row">
<div class="row" v-if="step === 1">
<div class="col">
<div class="row m-b-15">
<div class="col-6 p-r-5">
<validation-wrapper-component selecatable :validator="$v.parameters.district_id">
<label>District</label>
<selectable-component :endpoint="route('api.address.district.list')" section="districtListSection" valueColumn="id" :labelColumn="['city']" v-model="parameters.district_id"></selectable-component>
</validation-wrapper-component>
</div>
<div class="col-4 p-l-5">
<validation-wrapper-component :validator="$v.parameters.post_code">
<label>Post Code</label>
<input class="form-control" name="post_code" v-model="parameters.post_code">
</validation-wrapper-component>
<div class="row">
<div class="col">
<div class="row m-b-15">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.street_one">
<label>Address Line 1</label>
<input class="form-control" name="street_one" v-model="parameters.street_one">
</validation-wrapper-component>
</div>
</div>
<div class="row m-b-15">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.street_two">
<label>Address Line 2</label>
<input class="form-control" name="street_two" v-model="parameters.street_two">
</validation-wrapper-component>
</div>
</div>
<div class="row m-b-15">
<div class="col-7 p-r-5">
<validation-wrapper-component selecatable :validator="$v.parameters.district_id">
<label>District</label>
<selectable-component :endpoint="route('api.address.district.list')" section="districtListSection" valueColumn="id" :labelColumn="['city']" v-model="parameters.district_id"></selectable-component>
</validation-wrapper-component>
</div>
<div class="col-5 p-l-5">
<validation-wrapper-component :validator="$v.parameters.post_code">
<label>Post Code</label>
<input class="form-control" name="post_code" v-model="parameters.post_code">
</validation-wrapper-component>
</div>
</div>
</div>
</div>
<div class="row m-b-15">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.street_one">
<label>Address Line 1</label>
<input class="form-control" name="street_one" v-model="parameters.street_one">
</validation-wrapper-component>
</div>
</div>
<div class="row m-b-15">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.street_two">
<label>Address Line 2</label>
<input class="form-control" name="street_two" v-model="parameters.street_two">
</validation-wrapper-component>
<div class="row">
<div class="col text-right">
<button type="button" class="btn btn-sm btn-success btn-block b-rad-none" @click="updateStep(2)">{{(type === 3) ? "Update" : "Save" }} Billing Address</button>
<button v-show="type === 3" type="button" class="btn btn-sm bg-master-lighter b-rad-none m-l-5" @click="closeForm()">Cancel</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row mb-3">
<div class="row" v-if="step === 2">
<div class="col">
<div class="row">
<div class="col text-right">
<button type="button" class="btn btn-sm btn-success b-rad-none" @click="submitForm()">{{(this.type==3)?"Update":"Create"}} Billing Address</button>
<button v-show="this.type==3" type="button" class="btn btn-sm bg-master-lighter b-rad-none m-l-5" @click="closeForm()">Cancel</button>
<div class="row m-b-15">
<div class="col">
<div class="row">
<div class="col">
<div class="padding-15 bg-master-lightest">
<p class="muted">Billing Address</p>
<p class="m-b-0">{{parameters.street_one}} {{parameters.street_two}}, {{districts[parseFloat(parameters.district_id) - 1].city}} {{parameters.post_code}} {{districts[parseFloat(parameters.district_id) - 1].state.name}}, {{districts[parseFloat(parameters.district_id) - 1].country.name}}</p>
</div>
</div>
</div>
</div>
</div>
<div class="row m-b-15">
<div class="col">
<div class="row">
<div class="col-auto p-r-5">
<button type="button" class="btn btn-sm bg-master-lighter b-rad-none" @click="updateStep(1)">Edit Billing Address</button>
</div>
<div class="col p-l-0">
<button type="button" class="btn btn-sm btn-success btn-block b-rad-none" @click="submitForm()">Confirm Billing Address</button>
</div>
</div>
</div>
</div>
</div>
@@ -84,8 +116,14 @@
}
}
},
computed: {
districts () {
return this.$store.getters.getSelectableList('original_districtListSection');
}
},
data() {
return {
step: 1,
parameters : {
company_id: this.id,
street_one: '',
@@ -105,8 +143,15 @@
}
},
methods:{
updateStep(step){
if(step === 2){
if(!this.validate()){ return; }
}
this.step = step
},
submitForm(){
if(this.type==3){
if(this.type === 3){
this.submit((this.route('api.address.update',this.addressData.id)), 'put', 'bookingDetailSection', true, true)
}else {
this.submit((this.route('api.address.create')), 'post', 'bookingDetailSection', true, true)
@@ -116,7 +161,7 @@
this.$root.$emit('updateAddressForm', {}, false);
},
successHandler(response){
if(this.type==3){
if(this.type === 3){
this.closeForm();
this.$store.dispatch('reloadList', {'name': "addresslist"});
}else {
@@ -1,10 +1,7 @@
<template>
<div class="row">
<div class="col">
<button class="btn btn-lg btn-default bg-master-lightest b-rad-none all-caps fs-12" data-dismiss="modal">Cancel</button>
</div>
<div class="col-auto">
<button class="btn btn-lg btn-success b-rad-none all-caps fs-12" @click="submitForm()">Set as default</button>
<button class="btn btn-block btn-sm btn-success b-rad-none" @click="submitForm()">Update Default Billing Address</button>
</div>
</div>
</template>
@@ -2,7 +2,7 @@
<div class="row">
<div class="col">
<div class="border-sm row align-items-center m-b-15 parentContainer position-relative">
<div class="col-auto p-r-0">
<div class="col-auto p-r-0 d-none d-md-block">
<div class="padding-5 bg-master-lightest">
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"
width="30" height="30"
@@ -10,61 +10,70 @@
style=" fill:#000000;"><defs><linearGradient x1="86" y1="104.14063" x2="86" y2="140.57775" gradientUnits="userSpaceOnUse" id="color-1_44825_gr1"><stop offset="0" stop-color="#4ec9ff"></stop><stop offset="1" stop-color="#2bffe6"></stop></linearGradient><linearGradient x1="86" y1="16.125" x2="86" y2="159.93044" gradientUnits="userSpaceOnUse" id="color-2_44825_gr2"><stop offset="0" stop-color="#009add"></stop><stop offset="1" stop-color="#00baa4"></stop></linearGradient></defs><g fill="none" fill-rule="nonzero" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="none" font-weight="none" font-size="none" text-anchor="none" style="mix-blend-mode: normal"><path d="M0,172v-172h172v172z" fill="none"></path><g><path d="M121.41588,139.75h-70.83175c-2.53431,0 -3.66575,-3.18469 -1.6985,-4.78106l33.72544,-27.40175c1.97531,-1.60444 4.80256,-1.60444 6.77787,0l33.72544,27.40175c1.96725,1.59638 0.83581,4.78106 -1.6985,4.78106z" fill="url(#color-1_44825_gr1)"></path><path d="M148.135,71.77238l-8.385,-8.385v-28.42031c0,-4.46125 -3.63081,-8.09206 -8.09206,-8.09206h-2.65794v-2.65794c0,-4.46125 -3.63081,-8.09206 -8.09206,-8.09206h-69.81587c-4.46125,0 -8.09206,3.63081 -8.09206,8.09206v2.65794h-2.65794c-4.46125,0 -8.09206,3.63081 -8.09206,8.09206v28.42031l-8.385,8.385c-1.5265,1.52381 -2.365,3.55019 -2.365,5.70825v64.95688c0,7.40944 6.02806,13.4375 13.4375,13.4375h102.125c7.40944,0 13.4375,-6.02806 13.4375,-13.4375v-64.95688c0,-2.15806 -0.84119,-4.18444 -2.365,-5.70825zM77.60156,91.96356l-0.30906,0.24725c-1.28731,-1.79525 -2.0425,-3.92375 -2.0425,-6.21081c0,-5.92862 4.82138,-10.75 10.75,-10.75c5.92863,0 10.75,4.82138 10.75,10.75c0,2.26287 -0.70413,4.41019 -2.01294,6.235l-0.34131,-0.27412c-4.93962,-3.95063 -11.84919,-3.95063 -16.79419,0.00269zM86,69.875c-8.89294,0 -16.125,7.23206 -16.125,16.125c0,3.53406 1.14487,6.85581 3.18738,9.59438l-10.578,8.46025l-3.35937,-2.6875v-55.88388c6.95256,-1.06963 12.16094,-6.28069 13.23325,-13.23325h27.2835c1.06963,6.95256 6.28069,12.16094 13.23325,13.23325v55.88656l-3.35937,2.6875l-10.56994,-8.45488c2.07744,-2.79231 3.17931,-6.10869 3.17931,-9.60244c0,-8.89294 -7.23206,-16.125 -16.125,-16.125zM58.179,107.5l-31.304,25.04481v-50.08694zM145.125,82.45519v50.08963l-31.30669,-25.04481zM144.33488,75.5725c0.11825,0.11825 0.18006,0.27412 0.27412,0.4085l-4.859,3.88612v-8.8795zM131.65794,32.25c1.49962,0 2.71706,1.21744 2.71706,2.71706v49.20275l-5.375,4.3v-56.21981zM51.09206,21.5h69.81856c1.49694,0 2.71438,1.21744 2.71438,2.71706v68.55275l-5.375,4.3v-56.75731h-2.6875c-6.22694,0 -10.75,-4.52306 -10.75,-10.75v-2.6875h-37.625v2.6875c0,6.22694 -4.52306,10.75 -10.75,10.75h-2.6875v56.75731l-5.375,-4.3v-68.55275c0,-1.49962 1.21744,-2.71706 2.71706,-2.71706zM40.34206,32.25h2.65794v56.21981l-5.375,-4.3v-49.20275c0,-1.49963 1.21744,-2.71706 2.71706,-2.71706zM32.25,70.98763v8.88219l-4.859,-3.88881c0.09406,-0.13438 0.15587,-0.29025 0.27412,-0.4085zM137.0625,150.5h-102.125c-4.44513,0 -8.0625,-3.61738 -8.0625,-8.0625v-3.00463l54.08325,-43.27144c2.96969,-2.37306 7.11381,-2.37306 10.08081,0l54.08594,43.26875v3.00731c0,4.44513 -3.61737,8.0625 -8.0625,8.0625z" fill="url(#color-2_44825_gr2)"></path></g></g></svg>
</div>
</div>
<div class="col-6 col-sm-auto">
<div class="col-auto">
<div class="row">
<div class="col-auto p-r-10 all-caps">
<div class="font-heading all-caps fs-11 bold">{{this.item.marking}}</div>
<div class="font-heading all-caps bold">{{this.item.marking}}</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="font-heading all-caps fs-10 muted">{{this.item.created_at}}</div>
<div class="font-heading all-caps muted fs-11">{{this.item.created_at}}</div>
</div>
</div>
</div>
<div class="col-6 col-sm d-none d-lg-block" v-if="$store.getters.isAdmin">
<div class="col d-none d-lg-block" v-if="$store.getters.isAdmin">
<div class="font-heading fs-10 muted all-caps">Marking</div>
<div class="font-heading fs-12">
<div class="font-heading">
<a :href="route('customer.profile', item.company.reference)">{{this.item.company.reference}}</a>
</div>
</div>
<div class="col-6 col-sm-auto d-none d-lg-block">
<div class="col-auto d-none d-lg-block">
<div class="font-heading fs-10 muted all-caps">Currency</div>
<div class="font-heading fs-12 bold">
<span class="flag-icon fs-12" :class="'flag-icon-'+item.convertible_currency.country.short_code.toLowerCase()"></span> {{this.item.convertible_currency.short_code}}
<div class="font-heading bold">
<span class="flag-icon" :class="'flag-icon-'+item.convertible_currency.country.short_code.toLowerCase()"></span> {{this.item.convertible_currency.short_code}}
</div>
</div>
<div class="col-6 col-sm-auto d-none d-lg-block">
<div class="col-auto d-none d-lg-block">
<div class="font-heading fs-10 muted all-caps">Transfer Type</div>
<div class="font-heading fs-11">{{this.item.service.name}}</div>
<div class="font-heading fs-12">{{this.item.service.name}}</div>
</div>
<div class="col-6 col-sm d-none d-lg-block">
<div class="col">
<div class="font-heading fs-10 muted all-caps">Payable Amount</div>
<div class="font-heading fs-11 text-success bold">{{this.item.amount}} {{this.item.fixed_currency.short_code}}</div>
<div class="font-heading text-success bold">{{this.item.amount}} {{this.item.fixed_currency.short_code}}</div>
</div>
<div class="col-6 col-sm-auto d-none d-lg-block" v-if="$store.getters.isCustomer">
<div class="col-auto" v-if="$store.getters.isCustomer">
<div class="font-heading fs-10 muted all-caps">status</div>
<div class="font-heading fs-8 all-caps text-master btn-rounded p-l-10 p-r-10 lh-15 mt-1" :class="[{'bg-warning': item.status !== 3}, {'bg-success': item.status === 3} ]">
<div class="font-heading all-caps text-master btn-rounded p-l-10 p-r-10 lh-15 mt-1" :class="[{'bg-warning': item.status !== 3}, {'bg-success': item.status === 3} ]">
{{item.status === 3 ? 'Complete' : 'In Progress'}}
</div>
</div>
<div class="col-auto hide d-none d-lg-block" :class="[{'invisible': !item.service.configurations.billable}]" v-if="$store.getters.isCustomer">
<div class="font-heading fs-10 muted all-caps">Billing</div>
<div class="font-heading fs-8 all-caps text-danger btn-rounded bg-master-lightest p-l-10 p-r-10 lh-15 mt-1">
<div class="font-heading all-caps text-danger btn-rounded bg-master-lightest p-l-10 p-r-10 lh-15 mt-1">
Pending...
</div>
</div>
<div class="col-2 p-r-5 parentContainer position-static">
<div class="row align-items-center">
<div class="col-auto ml-auto position-static">
<div class="btn btn-xs btn-default b-rad-none requestModal" v-if="item.status !== 5 && item.paid_amount === 0 && item.floating_amount === 0 && $store.getters.isAdmin" data-type="cancelBooking">
<div class="col col-md-2 parentContainer position-static">
<div class="row align-items-center justify-content-end">
<div class="col-auto position-static no-padding">
<div class="btn btn-sm btn-default b-rad-none no-border requestModal" v-if="item.status !== 5 && item.paid_amount === 0 && item.floating_amount === 0 && $store.getters.isAdmin" data-type="cancelBooking">
<i class="fa fa-fw fa-times text-danger"></i>
</div>
<div class="btn btn-xs btn-default b-rad-none requestModal" v-if="item.status === 5 && item.paid_amount === 0 && item.floating_amount === 0 && $store.getters.isAdmin" data-type="restoreBooking">
<div class="btn btn-sm btn-default b-rad-none no-border requestModal" v-if="item.status === 5 && item.paid_amount === 0 && item.floating_amount === 0 && $store.getters.isAdmin" data-type="restoreBooking">
<i class="fa fa-fw fa-history text-success"></i>
</div>
<a class="btn btn-xs btn-info b-rad-none" :href="route('booking.details', item.marking)">
<i class="fa fa-angle-right fa-fw"></i>
</div>
<div class="col-auto no-padding">
<div class="btn btn-sm btn-default b-rad-none d-md-none no-border" @click="expanded = !expanded">
<i class="fa fa-fw" :class="[{'fa-angle-up': expanded}, {'fa-angle-down': !expanded}]"></i>
</div>
</div>
<div class="col-auto p-l-0">
<a :href="route('booking.details', item.marking)">
<div class="btn btn-sm btn-info b-rad-none" @click="expanded = !expanded">
<i class="fa fa-angle-right fa-fw"></i>
</div>
</a>
</div>
</div>
@@ -75,49 +84,26 @@
<restore-booking-form-component :data="item" section="oderList" class="text-center"></restore-booking-form-component>
</modal-component>
</div>
<div class="col-2 p-r-5 parentContainer position-static d-block d-sm-none">
<div class="btn btn-xs btn-default b-rad-none position-absolute" style="top: 7px; right: 10px;" @click="expanded = !expanded">
<i class="fa fa-fw" :class="[{'fa-angle-up': expanded}, {'fa-angle-down': !expanded}]"></i>
</div>
</div>
</div>
<div class="row" v-if="expanded">
<div class="col b-b b-grey m-l-10 m-r-10 m-b-10 p-b-10" style="margin-top:-15px">
<div class="col b-b b-grey m-b-15 p-b-15">
<div class="row">
<div class="col-6 col-sm" v-if="$store.getters.isAdmin">
<div class="font-heading fs-10 muted all-caps">Marking</div>
<div class="font-heading fs-12">
<a :href="route('customer.profile', item.company.reference)">{{this.item.company.reference}}</a>
</div>
</div>
<div class="col-6 col-sm-auto">
<div class="font-heading fs-10 muted all-caps">Currency</div>
<div class="font-heading fs-12 bold">
<span class="flag-icon fs-12" :class="'flag-icon-'+item.convertible_currency.country.short_code.toLowerCase()"></span> {{this.item.convertible_currency.short_code}}
</div>
</div>
<div class="col-6 col-sm-auto">
<div class="font-heading fs-10 muted all-caps">Transfer Type</div>
<div class="font-heading fs-11">{{this.item.service.name}}</div>
</div>
<div class="col-6 col-sm">
<div class="font-heading fs-10 muted all-caps">Payable Amount</div>
<div class="font-heading fs-11 text-success bold">{{this.item.amount}} {{this.item.fixed_currency.short_code}}</div>
</div>
<div class="col-6 col-sm-auto" v-if="$store.getters.isCustomer">
<div class="font-heading fs-10 muted all-caps">status</div>
<div class="font-heading fs-8 all-caps text-master btn-rounded p-l-10 p-r-10 lh-15 mt-1" :class="[{'bg-warning': item.status !== 3}, {'bg-success': item.status === 3} ]">
{{item.status === 3 ? 'Complete' : 'In Progress'}}
</div>
</div>
<div class="col-auto hide" :class="[{'invisible': !item.service.configurations.billable}]" v-if="$store.getters.isCustomer">
<div class="font-heading fs-10 muted all-caps">Billing</div>
<div class="font-heading fs-8 all-caps text-danger btn-rounded bg-master-lightest p-l-10 p-r-10 lh-15 mt-1">
Pending...
</div>
</div>
<div class="col-auto">
<div class="font-heading fs-10 muted all-caps">Currency</div>
<div class="font-heading bold">
<span class="flag-icon" :class="'flag-icon-'+item.convertible_currency.country.short_code.toLowerCase()"></span> {{this.item.convertible_currency.short_code}}
</div>
</div>
<div class="col-auto">
<div class="font-heading fs-10 muted all-caps">Transfer Type</div>
<div class="font-heading">{{this.item.service.name}}</div>
</div>
<div class="col text-right" v-if="$store.getters.isAdmin">
<div class="font-heading fs-10 muted all-caps">Marking</div>
<div class="font-heading">
<a :href="route('customer.profile', item.company.reference)">{{this.item.company.reference}}</a>
</div>
</div>
</div>
</div>
</div>
@@ -26,7 +26,7 @@
</div>
</div>
</div>
<div class="col-auto">
<div v-if="item.status === 1" class="col-auto">
<div class="row parentContainer">
<div class="col p-l-0">
<button class="btn btn-xs btn-default bg-success b-rad-none no-border requestModal" data-type="approveDocument">
@@ -59,6 +59,39 @@
</div>
</div>
</div>
<div v-if="item.status === 2" class="col-auto">
<div class="row parentContainer">
<div class="col p-l-0">
<button class="btn btn-xs btn-default bg-danger b-rad-none no-border requestModal" data-type="deleteDocument">
<i class="fa fa-times text-white"></i>
</button>
<modal-component small type="deleteDocument">
<div class="row">
<div class="col text-center">
<div class="row">
<div class="col text-center">
<div class="row m-b-20">
<div class="col">
<h5 class="all-caps">Are you Sure?</h5>
<div class="fs-11">Are you sure you want to delete this docuement?</div>
</div>
</div>
<div class="row">
<div class="col p-r-5">
<div data-dismiss="modal" class="btn btn-sm btn-default bg-master-lighter btn-block b-rad-none">Cancel</div>
</div>
<div class="col p-l-5">
<div data-dismiss="modal" class="btn btn-sm btn-danger btn-block b-rad-none" @click="deleteDocument()">Delete</div>
</div>
</div>
</div>
</div>
</div>
</div>
</modal-component>
</div>
</div>
</div>
</div>
</div>
@@ -79,8 +112,12 @@
methods: {
approveDocument(status){
this.isLoading = true;
this.submit(this.route('api.company.identification.approval', this.item.owner.id, this.item.id, status), 'put', 'identificationVerificationSection', true, true);
this.submit(this.route('api.document.status.approve', this.item.id, status), 'put', 'identificationVerificationSection', true, true);
},
deleteDocument() {
this.isLoading = true;
this.submit(this.route('api.document.delete', this.item.id), 'delete', 'identificationVerificationSection', true, true);
}
},
mixins: [componentHandler, staticFormHandler]
}
@@ -1,7 +1,7 @@
<template>
<div class="row m-l-0 m-b-10 m-r-0 parentContainer" :class="[{'b-a': item.status === 4}, {'b-danger': item.status === 4}]" >
<div class="col">
<div class="row" v-if="item.type === 1">
<div class="row" v-if="!item.transaction_bill">
<div class="col">
<div class="row">
<div class="col p-t-10 p-b-10 p-r-0 pointer" @click="clickExpand()" :class="[{'bg-master-lighter': item.status === 1}, {'bg-white': item.status !== 1 && item.status !== 4}]">
@@ -33,52 +33,52 @@
</div>
<div class="row align-items-center h-100" v-if="item.payment_method === 5 && item.status === 1">
<div class="col">
<a :href="'https://www.billplz.com/bills/'+item.payment_reference"><i class="fa fa-repeat text-success"></i></a>
<a :href="route('billplz.bill', item.payment_reference)"><i class="fa fa-repeat text-success"></i></a>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row" v-if="item.type === 3">
<div class="row" v-if="item.transaction_bill">
<div class="col">
<div class="row">
<div class="col p-t-10 p-b-10 p-r-0 pointer" @click="clickExpand()" :class="[{'bg-master-lighter': item.status === 1}, {'bg-white': item.status !== 1 && item.status !== 4}]">
<div class="col p-t-10 p-b-10 p-r-0 pointer" @click="clickExpand()" :class="[{'bg-master-lighter': item.transaction_bill.status === 1}, {'bg-white': item.transaction_bill.status !== 1 && item.transaction_bill.status !== 4}]">
<div class="row m-b-5">
<div class="col-auto">
<div class="font-heading fs-8 muted all-caps">Status</div>
<div class="font-heading fs-10 bold" :class="[{'text-danger': item.status === 1 || item.status === 4}, {'text-success': item.status !== 1 && item.status !== 4}]">
{{ item.status === 1 ? 'Processing Payment' : 'Transferred'}}
<div class="font-heading fs-10 bold" :class="[{'text-danger': item.transaction_bill.status === 1 || item.transaction_bill.status === 4}, {'text-success': item.transaction_bill.status !== 1 && item.transaction_bill.status !== 4}]">
{{ item.transaction_bill.status === 1 ? 'Processing Payment' : 'Transferred'}}
</div>
</div>
<div class="col-auto p-l-0">
<div class="font-heading fs-8 muted all-caps">Payment Amount</div>
<div class="font-heading fs-10 bold">
{{item.original_currency.short_code}} {{(Math.round((item.original_amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
{{item.transaction_bill.original_currency.short_code}} {{(Math.round((item.transaction_bill.original_amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
</div>
</div>
<div class="col-auto" v-if="$store.getters.isAdmin">
<div class="font-heading fs-8 muted all-caps">Supplier</div>
<div class="font-heading fs-10 bold">
{{item.issuer_name}}
{{item.transaction_bill.issuer_name}}
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="font-heading fs-8 all-caps" >{{ item.status === 1 ? 'Paid On: ' + customerBooking.updated_at : 'Transferred On:' + item.updated_at }}</div>
<div class="font-heading fs-8 all-caps" >{{ item.transaction_bill.status === 1 ? 'Paid On: ' + item.updated_at : 'Transferred On:' + item.transaction_bill.updated_at }}</div>
</div>
</div>
</div>
<div class="col-auto" v-if="item.status !== 3 && item.status !== 2" :class="[{'bg-master-light': item.status === 1}, {'bg-master-lighter': item.status === 2}]">
<div class="col-auto" v-if="item.transaction_bill.status !== 3 && item.transaction_bill.status !== 2" :class="[{'bg-master-light': item.transaction_bill.status === 1}, {'bg-master-lighter': item.transaction_bill.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>
<i class="fa" :class="[{'fa-cloud-download': item.transaction_bill.status === 1 || item.transaction_bill.status === 2}, {'fa-ban': item.transaction_bill.status === 4}, {'muted': item.transaction_bill.status === 1 || item.transaction_bill.status === 2}, {'text-danger': item.transaction_bill.status === 4}]"></i>
</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]">
<div class="col-auto bg-success" v-if="item.transaction_bill.status === 2 || item.transaction_bill.status === 3">
<document-file-viewer-component class="h-100" :file="item.transaction_bill.documents.files[0]">
<template slot="button">
<div class="row align-items-center h-100">
<div class="col">
@@ -98,7 +98,7 @@
<div class="font-heading all-caps fs-10">Recipient Gets</div>
</div>
<div class="col-auto text-right">
<div class="font-heading fs-10">{{this.customerBooking.original_currency.short_code}} {{(item.original_amount).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}</div>
<div class="font-heading fs-10">{{item.original_currency.short_code}} {{(item.original_amount).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}</div>
</div>
</div>
<div class="row align-items-end bold m-b-10 text-primary">
@@ -106,7 +106,7 @@
<div class="font-heading all-caps fs-10">Rate</div>
</div>
<div class="col-auto text-right">
<div class="font-heading fs-10 ">{{(Math.round((this.customerBooking.currency_rate + Number.EPSILON) * 100000) / 100000).toFixed(5) }}</div>
<div class="font-heading fs-10 ">{{(Math.round((item.currency_rate + Number.EPSILON) * 100000) / 100000).toFixed(5) }}</div>
</div>
</div>
<div class="row align-items-end m-b-10 hint-text">
@@ -114,7 +114,7 @@
<div class="font-heading all-caps fs-10">Transfer Charges</div>
</div>
<div class="col-auto text-right">
<div class="font-heading fs-10">MYR {{(Math.round((this.customerBooking.service_charge + Number.EPSILON) * 100) / 100).toFixed(2)}}</div>
<div class="font-heading fs-10">MYR {{(Math.round((item.service_charge + Number.EPSILON) * 100) / 100).toFixed(2)}}</div>
</div>
</div>
<div class="row align-items-end m-b-5 hint-text">
@@ -122,7 +122,7 @@
<div class="font-heading all-caps fs-10">Tax</div>
</div>
<div class="col-auto text-right">
<div class="font-heading fs-10">MYR {{(Math.round((this.customerBooking.tax + Number.EPSILON) * 100) / 100).toFixed(2)}}</div>
<div class="font-heading fs-10">MYR {{(Math.round((item.tax + Number.EPSILON) * 100) / 100).toFixed(2)}}</div>
</div>
</div>
<div class="row align-items-end m-b-10 bold text-success">
@@ -130,15 +130,15 @@
<div class="font-heading all-caps fs-10">Your Payment</div>
</div>
<div class="col-auto text-right">
<div class="font-heading fs-12">MYR {{(Math.round((this.customerBooking.amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}</div>
<div class="font-heading fs-12">MYR {{(Math.round((item.amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="font-heading all-caps fs-10 m-b-5">Your Payment Proof</div>
<div class="row no-margin" v-if="customerBooking.payment_method !== 5">
<div v-if="customerBooking.documents != null">
<div v-for="file in customerBooking.documents.files" v-bind:key="file.id" class="col-auto no-padding m-r-5">
<div class="row no-margin" v-if="item.payment_method !== 5">
<div v-if="item.documents != null">
<div v-for="file in item.documents.files" v-bind:key="file.id" class="col-auto no-padding m-r-5">
<document-file-viewer-component :file="file">
<template slot="button">
<div class="icon-thumbnail fs-11 text-white icon-25 bg-primary btn-rounded float-left m-r-5">
@@ -149,8 +149,8 @@
</div>
</div>
</div>
<div class="row no-margin" v-if="customerBooking.payment_method === 5 && (customerBooking.status === 2 || customerBooking.status === 3)">
<a :href="'https://www.billplz.com/bills/'+customerBooking.payment_reference" target="_blank">
<div class="row no-margin" v-if="item.payment_method === 5 && (item.status === 2 || item.status === 3)">
<a :href="route('billplz.bill', item.payment_reference)" target="_blank">
<div class="icon-thumbnail fs-11 text-white icon-25 bg-primary btn-rounded float-left m-r-5">
<i class="fa fa-file-image-o fs-10"></i>
</div>
@@ -159,8 +159,8 @@
</div>
<div class="col text-right">
<div class="font-heading all-caps fs-10 m-b-5">Our Payment Proof</div>
<div class="row no-margin justify-content-end" v-if="item.type === 3 && (item.status === 2 || item.status === 3)">
<div v-for="file in item.documents.files" v-bind:key="file.id" class="col-auto no-padding m-l-5">
<div class="row no-margin justify-content-end" v-if="(item.transaction_bill.status === 2 || item.transaction_bill.status === 3)">
<div v-for="file in item.transaction_bill.documents.files" v-bind:key="file.id" class="col-auto no-padding m-l-5">
<document-file-viewer-component :file="file">
<template slot="button">
<div class="icon-thumbnail fs-11 text-white icon-25 bg-primary btn-rounded float-left m-r-0">
@@ -230,9 +230,9 @@
</div>
</div>
</div>
<div class="row m-r-0 m-b-10" v-if="refundMethod.name == 'Fully Refund'">
<div class="row m-r-0 m-b-10" v-if="refundMethod.name === 'Fully Refund'">
<div class="col p-r-0">
<validation-wrapper-component :validator="parameters.amount" v-if="refundMethod.name == 'Fully Refund'">
<validation-wrapper-component :validator="parameters.amount" v-if="refundMethod.name === 'Fully Refund'">
<label>Amount</label>
<input class="form-control disabled" name="amount" v-model.lazy="amount" disabled>
</validation-wrapper-component>
@@ -245,7 +245,7 @@
</div>
</div>
</div>
<div class="row m-r-0 m-b-10" v-if="refundMethod.name == 'Partially Refund'">
<div class="row m-r-0 m-b-10" v-if="refundMethod.name === 'Partially Refund'">
<div class="col p-r-0">
<validation-wrapper-component :validator="parameters.amount">
<label>Amount</label>
@@ -302,11 +302,6 @@
section: 'bookingDetailSection',
}
},
computed: {
customerBooking(){
return this.item.type === 1 ? this.item : this.item.customer_booking;
}
},
methods: {
submitForm(){
this.submit(this.route('api.booking.refund.create', this.data.booking.id, this.data.id), 'post', this.section, true, true);
@@ -316,7 +311,7 @@
this.expandPaymentDetails = !this.expandPaymentDetails;
},
clickExpand(){
if (this.expandPaymentDetails == false && this.expandRefund == false) {
if (this.expandPaymentDetails === false && this.expandRefund === false) {
this.expandPaymentDetails = !this.expandPaymentDetails;
} else {
this.expandRefund = false;
@@ -41,6 +41,14 @@
</div>
</div>
<bank-in-component :data="item"></bank-in-component>
<div class="row" v-if="item.status === 1 || 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>
@@ -2,43 +2,41 @@
<div class="row m-b-10 parentContainer">
<div class="col">
<loading-component style="height: 200px; top: 0;" key="1" color="success" v-show="isLoading"></loading-component>
<div class="row" v-show="!isLoading">
<div class="row p-b-5 b-b b-grey" v-show="!isLoading">
<div class="col">
<div class="row align-items-center">
<div class="col p-t-5 p-b-5">
<div class="row">
<div class="col-6 col-md-6 col-lg-3">
<div class="font-heading fs-10 muted all-caps">Reference</div>
<div class="font-heading fs-10">
{{item.bill_no}}
</div>
</div>
<div class="col-6 col-md-6 col-lg-3">
<div class="font-heading fs-10 muted all-caps">Transfer No.</div>
<a :href="route('booking.details', item.booking.marking)">
<div class="font-heading fs-10">
{{item.booking.marking}}
</div>
</a>
</div>
<div class="col-6 col-md-auto">
<div class="font-heading fs-10 muted all-caps">Marking</div>
<div class="font-heading fs-10">
{{item.booking.company.reference}}
</div>
</div>
<div class="col text-lg-right">
<div class="row">
<div class="col">
<div class="row m-b-10">
<div class="col-auto">
<div class="font-heading fs-10 muted all-caps">Date</div>
<div class="font-heading fs-10">
{{item.documents ? item.documents.created_at : item.updated_at}}
{{item.payment_method === 5 || item.payment_method === 4 ? item.updated_at : item.documents.created_at}}
</div>
</div>
<div class="col-auto">
<div class="font-heading fs-10 muted all-caps">reference</div>
<div class="font-heading fs-10">
<a :href="route('booking.details', item.booking.marking)">{{item.booking.marking}}</a>
</div>
</div>
<div class="col-auto">
<div class="font-heading fs-10 muted all-caps">Marking</div>
<div class="font-heading fs-10">
<a :href="route('customer.profile', item.booking.company.reference)">{{item.booking.company.reference}}</a>
</div>
</div>
<div class="col text-right">
<div class="font-heading fs-10 muted all-caps">Amount</div>
<div class="font-heading fs-14 text-success bold">
{{(Math.round((item.amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
</div>
</div>
</div>
<div class="row m-t-10">
<div class="col-6 col-md-6 col-lg-3">
<div class="row m-b-10">
<div class="col-auto">
<div class="font-heading fs-10 muted all-caps">Payment Proof</div>
<div class="row no-margin" v-if="item.payment_method !== 5">
<div v-for="file in item.documents.files" v-bind:key="file.id" class="col-6 col-md-auto no-padding">
<div class="row no-margin" v-if="item.payment_method !==5 && item.payment_method !==4">
<div v-for="file in item.documents.files" v-bind:key="file.id" class="col-auto no-padding">
<document-file-viewer-component :file="file">
<template slot="button">
<div class="icon-thumbnail fs-11 text-white icon-25 bg-primary btn-rounded float-left m-r-5">
@@ -48,81 +46,78 @@
</document-file-viewer-component>
</div>
</div>
<div class="row no-margin" v-if="item.payment_method ===5">
<a :href="'https://www.billplz.com/bills/'+item.payment_reference" target="_blank">
<div class="icon-thumbnail fs-11 text-white icon-25 bg-complete btn-rounded float-left m-r-5">
Bz
</div>
</a>
</div>
</div>
<div class="col-6 col-md-6 col-lg-3" >
<div class="font-heading fs-10 muted all-caps">Amount</div>
<div class="font-heading fs-12 text-success bold">
MYR {{(Math.round((item.amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
<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 class="col">
<div class="font-heading fs-10 muted all-caps">Original</div>
<div class="font-heading fs-10 muted all-caps">Booking</div>
<div class="font-heading fs-10">
{{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 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>
</button>
<button class="btn btn-xs btn-success b-rad-none requestModal" data-type="approvePayment">
<i class="fa fa-check fa-fw"></i>
</button>
<modal-component small type="rejectPayment">
<div class="row">
<div class="col text-center">
<div class="col-auto">
<div class="row">
<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>
</button>
<button class="btn btn-xs btn-success b-rad-none requestModal" data-type="approvePayment">
<i class="fa fa-check fa-fw"></i>
</button>
<modal-component small type="rejectPayment">
<div class="row">
<div class="col text-center">
<div class="row m-b-20">
<div class="col">
<h5 class="all-caps">Reject Document</h5>
<div class="fs-11">Are you sure you want to reject this payment?</div>
</div>
</div>
<div class="row">
<div class="col p-r-5">
<div data-dismiss="modal" class="btn btn-sm btn-default bg-master-lighter btn-block b-rad-none">Cancel</div>
</div>
<div class="col p-l-5">
<div data-dismiss="modal" class="btn btn-sm btn-danger btn-block b-rad-none" @click="approvePayment('reject')">Reject</div>
<div class="col text-center">
<div class="row m-b-20">
<div class="col">
<h5 class="all-caps">Reject Document</h5>
<div class="fs-11">Are you sure you want to reject this payment?</div>
</div>
</div>
<div class="row">
<div class="col p-r-5">
<div data-dismiss="modal" class="btn btn-sm btn-default bg-master-lighter btn-block b-rad-none">Cancel</div>
</div>
<div class="col p-l-5">
<div data-dismiss="modal" class="btn btn-sm btn-danger btn-block b-rad-none" @click="approvePayment('reject')">Reject</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</modal-component>
<modal-component small type="approvePayment">
<div class="row">
<div class="col text-center">
</modal-component>
<modal-component small type="approvePayment">
<div class="row">
<div class="col text-center">
<div class="row m-b-20">
<div class="col">
<h5 class="all-caps">Approve Payment</h5>
<div class="fs-11">Are you sure you want to approve this payment?</div>
</div>
</div>
<div class="row">
<div class="col p-r-5">
<div data-dismiss="modal" class="btn btn-sm btn-default bg-master-lighter btn-block b-rad-none">Cancel</div>
</div>
<div class="col p-l-5">
<div data-dismiss="modal" class="btn btn-sm btn-success btn-block b-rad-none" @click="approvePayment('approve')">Approve</div>
<div class="col text-center">
<div class="row m-b-20">
<div class="col">
<h5 class="all-caps">Approve Payment</h5>
<div class="fs-11">Are you sure you want to approve this payment?</div>
</div>
</div>
<div class="row">
<div class="col p-r-5">
<div data-dismiss="modal" class="btn btn-sm btn-default bg-master-lighter btn-block b-rad-none">Cancel</div>
</div>
<div class="col p-l-5">
<div data-dismiss="modal" class="btn btn-sm btn-success btn-block b-rad-none" @click="approvePayment('approve')">Approve</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</modal-component>
</div>
</modal-component>
</div>
</div>
</div>
</div>
@@ -1,9 +1,9 @@
<template>
<div class="row m-b-10 parentContainer">
<div class="row m-b-10 parentContainer ">
<div class="col">
<div class="row">
<div class="col">
<div class="row align-items-center pointer" @click="activate()">
<div class="row align-items-center pointer p-b-10 b-b b-grey" @click="activate()">
<div class="col-auto p-r-0">
<div class="b-grey b-a fs-10 btn-rounded icon-thumbnail icon-25 m-r-0" :class="[{'bg-primary': active}, {'bg-transparent': !active}]">
<i class="fa fa-check text-white fs-12 fa-fw"></i>
@@ -12,7 +12,23 @@
<div class="col p-t-5 p-b-5">
<div class="row">
<div class="col">
<div class="row m-b-5">
<div class="row m-b-10">
<div class="col-auto">
<div class="font-heading fs-10 muted all-caps">Date</div>
<div class="font-heading fs-10">
{{item.payment_method === 5 || item.payment_method === 4 ? item.updated_at : item.documents.created_at}}
</div>
</div>
<div class="col text-right">
<div class="font-heading fs-10 muted all-caps">timer</div>
<div class="font-heading fs-12 bold" :class="[{'text-success': item.interval.value === '+'}, {'text-danger': item.interval.value === '-'}]">
{{item.interval.value}}
{{item.interval.duration}}
days
</div>
</div>
</div>
<div class="row m-b-10">
<div class="col-auto">
<div class="font-heading fs-10 muted all-caps">reference</div>
<div class="font-heading fs-10">
@@ -25,9 +41,17 @@
<a :href="route('customer.profile', item.booking.company.reference)">{{item.booking.company.reference}}</a>
</div>
</div>
<div class="col-auto">
<div class="font-heading fs-10 muted all-caps">Currency</div>
<div class="font-heading fs-10">
<span class="flag-icon" :class="'flag-icon-'+item.original_currency.country.short_code.toLowerCase()"></span> {{item.original_currency.short_code}}
</div>
</div>
</div>
<div class="row">
<div class="col-auto">
<div class="font-heading fs-10 muted all-caps">Payment Proof</div>
<div class="row no-margin" v-if="item.payment_method !==5">
<div class="row no-margin" v-if="item.payment_method !==5 && item.payment_method !==4">
<div v-for="file in item.documents.files" v-bind:key="file.id" class="col-auto no-padding">
<document-file-viewer-component :file="file">
<template slot="button">
@@ -39,30 +63,29 @@
</div>
</div>
<div class="row no-margin" v-if="item.payment_method ===5">
<a :href="'https://www.billplz.com/bills/'+item.payment_reference" target="_blank">
<div class="icon-thumbnail fs-11 text-white icon-25 bg-complete btn-rounded float-left m-r-5">
Bz
</div>
</a>
<div class="col no-padding">
<a :href="route('billplz.bill', item.payment_reference)" target="_blank">
<div class="icon-thumbnail fs-11 text-white icon-25 bg-complete btn-rounded float-left m-r-5">
Bz
</div>
</a>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-auto">
<div class="font-heading fs-10 muted all-caps">Date</div>
<div class="font-heading fs-10">
{{item.payment_method === 5 ? item.updated_at : item.documents.created_at}}
<div class="row no-margin" v-if="item.payment_method ===4">
<div class="col no-padding">
<div class="font-heading fs-10">{{item.payment_reference}}</div>
</div>
</div>
</div>
<div class="col-auto">
<div class="font-heading fs-10 muted all-caps">Currency</div>
<div class="font-heading fs-10 muted all-caps">Service</div>
<div class="font-heading fs-10">
<span class="flag-icon" :class="'flag-icon-'+item.original_currency.country.short_code.toLowerCase()"></span> {{item.original_currency.short_code}}
{{item.booking.service.name}}
</div>
</div>
<div class="col">
<div class="col text-right">
<div class="font-heading fs-10 muted all-caps">Amount</div>
<div class="font-heading fs-12 text-success bold">
<div class="font-heading fs-14 text-success bold">
{{(Math.round((item.original_amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
</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
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>
@@ -2,74 +2,78 @@
<div class="row">
<div class="col">
<div class="row no-margin">
<div class="col p-t-25 p-t-25">
<div class="row">
<div class="col p-b-10 b-b b-grey">
<div class="row align-items-center">
<div class="col-auto p-r-0" style="min-width: 40px;">
<div class="font-heading all-caps fs-10"></div>
</div>
<div class="col p-r-5">
<div class="font-heading all-caps fs-10 muted">Stock Code</div>
</div>
<div class="col-4 p-r-5 p-l-5">
<div class="font-heading all-caps fs-10 muted">description</div>
</div>
<div class="col text-center p-r-5 p-l-5">
<div class="font-heading all-caps fs-10 muted">quantity</div>
</div>
<div class="col text-center p-r-5 p-l-5">
<div class="font-heading all-caps fs-10 muted">Unit Price</div>
</div>
<div class="col-1 text-center p-r-5 p-l-5">
<div class="font-heading all-caps fs-10 muted"></div>
</div>
<div class="col-1 text-right p-r-5 p-l-5">
<div class="font-heading all-caps fs-10 muted">Total</div>
</div>
<div class="col-auto text-center">
<button class="btn btn-xs btn-outline-success b-rad-none invisible"><i class="fa fa-check"></i></button>
<button class="btn btn-xs btn-outline-success b-rad-none invisible"><i class="fa fa-pencil"></i></button>
</div>
</div>
<div class="col p-b-15 p-l-0 p-r-0">
<div class="row align-items-center m-b-10">
<div class="col-auto p-r-0"><div class="icon-thumbnail icon-35 mr-0 btn-rounded text-white light animate__animated animate__infinite" :class="[{'bg-danger': !submitted}, {'animate__pulse': !submitted}, {'bg-success': submitted}]"><span v-if="data.status !==3">2</span><i class='fa fa-check' v-if="data.status === 3"></i></div></div>
<div class="col">
<div class="fs-14 bold all-caps" :class="[{'text-success': submitted}]">Purchase Order</div>
<p class="m-b-0 text-danger fs-12" v-if="!submitted">In order for us to process your order, you will need to provide us with your purchase order information.</p>
</div>
</div>
<div class="row m-b-20">
<div class="row">
<div class="col">
<div class="row" v-if="!submitted">
<div class="col p-b-5 p-t-5 b-b b-grey">
<div class="row align-items-center">
<div class="col-auto p-r-0" style="min-width: 40px;">
<div class="font-heading all-caps fs-10"></div>
</div>
<div class="col p-r-5">
<input type="text" class="form-control fs-10 b-rad-none" placeholder="Stock Code" v-model="product.stockCode" />
</div>
<div class="col-4 p-r-5 p-l-5">
<textarea class="form-control fs-10 b-rad-none" placeholder="Description" rows="1" @keyup="onlyEnglish($event)" v-model="product.description"></textarea>
</div>
<div class="col text-center p-r-5 p-l-5">
<input type="text" class="form-control fs-10 b-rad-none text-center" placeholder="Quantity" v-model.lazy="product.quantity" v-mask="'#########'"/>
</div>
<div class="col text-center p-r-5 p-l-5">
<input type="text" class="form-control fs-10 b-rad-none text-center" placeholder="Unit Price" v-model.lazy="product.unit_price" v-money="productPrice" />
</div>
<div class="col-1 text-center p-r-5 p-l-5">
<div class="font-heading all-caps fs-10">{{data.fixed_currency.short_code}}</div>
</div>
<div class="col-1 text-right p-r-5 p-l-5">
<div class="font-heading all-caps fs-10">{{(Math.round((productTotal + Number.EPSILON) * 100) / 100).toFixed(2) }}</div>
</div>
<div class="col-auto">
<button class="btn btn-xs btn-outline-success b-rad-none" @click="addProduct()"><i class="fa fa-check"></i></button>
<button class="btn btn-xs btn-outline-success b-rad-none invisible"><i class="fa fa-pencil"></i></button>
</div>
</div>
<div class="row" v-for="(product, index) in products">
<div class="col p-b-10 p-t-10 " :class="[{'b-grey' : index !== Object.keys(products).length - 1}, {'b-b' : index !== Object.keys(products).length - 1}]">
<purchase-order-item-form-component :data="product" :index="index" :currency="data.fixed_currency.short_code" :editable="!submitted" :section="section" @change="updateProduct($event, index)" v-on:remove="removeProduct(index)"></purchase-order-item-form-component>
</div>
</div>
<div class="row" v-for="(product, index) in products">
<div class="col p-b-10 p-t-10 b-b b-grey">
<purchase-order-item-form-component :data="product" :index="index" :currency="data.fixed_currency.short_code" :editable="!submitted" :section="section" @change="updateProduct($event, index)" v-on:remove="removeProduct(index)"></purchase-order-item-form-component>
<div class="row m-t-20" v-if="!submitted">
<div class="col">
<div class="row">
<div class="col-sm-12 col-md-4 pr-md-1">
<div class="form-group form-group-default b-rad-none">
<label>Stock Code</label>
<input type="text" class="form-control b-rad-none" v-model="product.stockCode" />
</div>
</div>
<div class="col-sm-12 col-md pl-md-1">
<div class="form-group form-group-default b-rad-none required">
<label>description</label>
<input class="form-control b-rad-none" rows="1" @keyup="onlyEnglish($event)" v-model="product.description">
</div>
</div>
</div>
<div class="row align-items-center">
<div class="col-sm-12 col-md-6 pr-md-1">
<div class="form-group form-group-default b-rad-none required">
<label>Unit Price</label>
<input type="text" class="form-control b-rad-none" placeholder="Unit Price" v-model.lazy="product.unit_price" v-money="productPrice" />
</div>
</div>
<div class="col-sm-12 col-md-6 pl-md-1">
<div class="form-group form-group-default b-rad-none no-padding no-border">
<div class="row no-margin">
<div class="col-auto bg-master-lightest pointer" @mousedown="updateQuantity" @mouseleave="clearInterval" @mouseup="clearInterval" @touchstart="updateQuantity" @touchend="clearInterval" @touchcancel="clearInterval">
<div class="row h-100 align-items-center">
<div class="col">
<i class="fa fa-minus"></i>
</div>
</div>
</div>
<div class="col no-padding">
<label class="p-t-5 p-l-5 text-center">Quantity</label>
<input type="text" class="form-control m-b-5 b-rad-none no-border text-center" v-model.lazy="product.quantity" v-mask="'#########'"/>
</div>
<div class="col-auto bg-master-lightest pointer" @mousedown="updateQuantity('add')" @mouseleave="clearInterval" @mouseup="clearInterval" @touchstart="updateQuantity('add')" @touchend="clearInterval" @touchcancel="clearInterval">
<div class="row h-100 align-items-center">
<div class="col">
<i class="fa fa-plus"></i>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12 col-md-4 p-b-15 pb-md-0">
<p class="m-b-0 small">Total</p>
<h6 class="no-margin bold text-complete">{{data.fixed_currency.short_code}} {{productTotal.toFixed(3)}}</h6>
</div>
<div class="col-sm-12 col-md">
<button class="btn btn-sm btn-block btn-complete b-rad-none" @click="addProduct()">Add Product</button>
</div>
</div>
</div>
</div>
</div>
@@ -77,7 +81,7 @@
</div>
</div>
<div class="row">
<div class="col-12 col-md-7">
<div class="col">
<div class="row" v-if="(Math.round((poTotal + Number.EPSILON) * 1000) / 1000).toFixed(3) > (Math.round((data.amount + Number.EPSILON) * 1000) / 1000).toFixed(3)">
<div class="col">
<div class="alert alert-warning padding-15" role="alert" v-if="false">
@@ -94,13 +98,14 @@
</div>
</div>
</div>
<div class="col-12 col-md-5" v-if="data.company.address">
<div class="row align-items-end p-t-10 p-b-10">
<div class="col">
<div class="font-heading all-caps fs-12 bold">Total:</div>
<div class="col-12 col-md-8" v-if="data.company.address">
<div class="row align-items-end m-r-0 p-b-20">
<div class="col"></div>
<div class="col-auto b-t b-grey p-t-10 p-l-0">
<h6 class="font-heading all-caps bold">Total:</h6>
</div>
<div class="col-auto text-right">
<div class="font-heading muted"><span v-if="!submitted" class="bold m-r-5" :class="[{'text-danger' : (Math.round((poTotal + Number.EPSILON) * 1000) / 1000).toFixed(3) !== (Math.round((data.amount + Number.EPSILON) * 1000) / 1000).toFixed(3)}, {'text-success' : (Math.round((this.poTotal + Number.EPSILON) * 1000) / 1000).toFixed(3) === (Math.round((this.data.amount + Number.EPSILON) * 1000) / 1000).toFixed(3)}]">{{(Math.round(( poTotal + Number.EPSILON) * 1000) / 1000).toFixed(3)}}/</span><span class="text-primary bold m-l-5">{{(Math.round((data.amount + Number.EPSILON) * 1000) / 1000).toFixed(3)}} {{data.fixed_currency.short_code}}</span></div>
<div class="col-auto b-t b-grey p-t-10 p-r-0">
<h6><span v-if="!submitted" class="bold m-r-5" :class="[{'text-danger' : (Math.round((poTotal + Number.EPSILON) * 1000) / 1000).toFixed(3) !== (Math.round((data.amount + Number.EPSILON) * 1000) / 1000).toFixed(3)}, {'text-success' : (Math.round((this.poTotal + Number.EPSILON) * 1000) / 1000).toFixed(3) === (Math.round((this.data.amount + Number.EPSILON) * 1000) / 1000).toFixed(3)}]">{{(Math.round(( poTotal + Number.EPSILON) * 1000) / 1000).toFixed(3)}}/</span><span class="text-primary bold m-l-5">{{(Math.round((data.amount + Number.EPSILON) * 1000) / 1000).toFixed(3)}} {{data.fixed_currency.short_code}}</span></h6>
</div>
</div>
<div class="row" v-if="poTotal > 0 && !submitted">
@@ -120,17 +125,12 @@
</div>
</div>
<div class="row" v-if="submitted && data.status !== 3">
<div class="col-12 col-md-7">
<div class="row m-b-15">
<div class="col">
<button class="btn btn-xs btn-success b-rad-none" v-if="$store.getters.isAdmin && data.purchase_order.status === 1" @click="submit(route('api.booking.po.approval', data.id), 'post', section, true, true)">Approve Purchase Order</button>
</div>
</div>
<div class="col-12 col-md-5 pr-md-0">
<div class="row">
<div class="col-12 col-lg-6">
<div class="col-12">
<document-file-viewer-component :file="data.documents.proforma_invoice.files[0]" v-if="data.documents.proforma_invoice">
<template slot="button">
<div class="text-center b-a b-info b-dashed b-thick padding-20 pointer m-b-10">
<div class="text-center bg-master-lightest padding-20 pointer m-b-10">
<div class="m-b-10">
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"
width="45" height="45"
@@ -141,7 +141,12 @@
</div>
</template>
</document-file-viewer-component>
<button class="btn btn-xs btn-danger b-rad-none btn-block" v-if="data.documents.proforma_invoice && data.outstanding_amount > 0" @click="submit(route('api.booking.proforma.create', data.id), 'post', section, true, true)">Regenerate Proforma Invoice</button>
<button class="btn btn-sm btn-danger b-rad-none btn-block" v-if="data.documents.proforma_invoice && data.outstanding_amount > 0" @click="submit(route('api.booking.proforma.create', data.id), 'post', section, true, true)">Regenerate Proforma Invoice</button>
</div>
</div>
<div class="row m-b-15" v-if="$store.getters.isAdmin && data.purchase_order.status === 1" >
<div class="col">
<button class="btn btn-sm btn-block btn-success b-rad-none" @click="submit(route('api.booking.po.approval', data.id), 'post', section, true, true)">Approve Purchase Order</button>
</div>
</div>
</div>
@@ -154,7 +159,7 @@
</div>
</div>
<button class="btn btn-xs all-caps b-rad-none btn-default bg-master-lightest w-100" @click="submitted = false">Edit Purchase Order</button>
<button class="btn btn-xs all-caps b-rad-none btn-success w-100 m-t-5" v-if="!data.documents.proforma_invoice && data.outstanding_amount != 0" @click="submit(route('api.booking.proforma.create', data.id), 'post', section, true, true)">Generate Proforma Invoice</button>
<button class="btn btn-xs all-caps b-rad-none btn-complete w-100 m-t-5" v-if="!data.documents.proforma_invoice && data.outstanding_amount != 0" @click="submit(route('api.booking.proforma.create', data.id), 'post', section, true, true)">Generate Proforma Invoice</button>
</div>
</div>
</div>
@@ -166,13 +171,14 @@
export default {
data(){
return {
interval:false,
submitted: false,
product: {
stockCode: '',
description: '',
quantity: 1,
unit_price: 0,
},
product: {
stockCode: '',
description: '',
quantity: 1,
unit_price: 0,
},
products: [],
}
},
@@ -182,7 +188,7 @@
},
computed: {
productTotal(){
return this.product.quantity * parseFloat((this.product.unit_price).toString().replace(',', ''));
return this.product.quantity * parseFloat((this.product.unit_price).toString().replaceAll(',', ''));
},
poTotal(){
return this.products.reduce(function(last, product) {
@@ -191,6 +197,15 @@
}
},
methods: {
updateQuantity(type){
if(!this.interval){
this.interval = setInterval(() => type === 'add' ? this.product.quantity++ : this.product.quantity > 1 ? this.product.quantity--:null , 80)
}
},
clearInterval(){
clearInterval(this.interval);
this.interval = false;
},
onlyEnglish(event){
let value = event.target.value,
regex = /^[^~`!@#$%^&*()_+=[\]\{}|;':",.\/<>?a-zA-Z0-9-]+$/;
@@ -1,34 +1,116 @@
<template>
<div class="row align-items-center">
<div class="col-auto p-r-0" style="min-width: 40px;">
<div class="font-heading all-caps fs-10">{{index + 1}}</div>
</div>
<div class="col p-r-5">
<div v-if="!isEdit" class="font-heading all-caps fs-10">{{product.stockCode}}</div>
<input v-if="isEdit" type="text" class="form-control fs-10 b-rad-none" placeholder="Stock Code" v-model="product.stockCode" />
</div>
<div class="col-4 p-r-5 p-l-5">
<div v-if="!isEdit" class="font-heading all-caps fs-10">{{product.description}}</div>
<textarea v-if="isEdit" class="form-control fs-10 b-rad-none" placeholder="Description" rows="1" @keyup="onlyEnglish($event)" v-model="product.description"></textarea>
</div>
<div class="col text-center p-r-5 p-l-5">
<div v-if="!isEdit" class="font-heading all-caps fs-10">{{product.quantity}}</div>
<input v-if="isEdit" type="text" class="form-control fs-10 b-rad-none text-center" placeholder="Quantity" v-model.lazy="product.quantity" v-mask="'#########'"/>
</div>
<div class="col text-center p-r-5 p-l-5">
<div v-if="!isEdit" class="font-heading all-caps fs-10">{{product.unit_price}}</div>
<input v-if="isEdit" type="text" class="form-control fs-10 b-rad-none text-center" placeholder="Unit Price" v-model.lazy="product.unit_price" v-money="productPrice" />
</div>
<div class="col-1 text-center p-r-5 p-l-5">
<div class="font-heading all-caps fs-10">{{currency}}</div>
</div>
<div class="col-1 text-right p-r-5 p-l-5">
<div class="font-heading all-caps fs-10">{{(Math.round((productTotal + Number.EPSILON) * 100) / 100).toFixed(2) }}</div>
</div>
<div class="col-auto" :class="[{'invisible': !editable}]">
<button class="btn btn-xs btn-outline-danger b-rad-none" @click="$emit('remove')"><i class="fa fa-times"></i></button>
<button v-if="!isEdit" class="btn btn-xs btn-outline-warning b-rad-none" @click="isEdit = !isEdit"><i class="fa fa-pencil"></i></button>
<button v-if="isEdit" class="btn btn-xs btn-outline-success b-rad-none" @click="updateProduct()"><i class="fa fa-check"></i></button>
<div class="col">
<div class="row" v-if="!isEdit">
<div class="col">
<div class="row align-items-center">
<div class="col-auto p-r-0" v-if="!editable"><div class="icon-thumbnail icon-35 mr-0 bg-master-lightest light">{{index + 1}}</div></div>
<div class="col-auto" v-if="editable">
<div @click="$emit('remove')" class="pointer">
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"
width="25" height="25"
viewBox="0 0 172 172"
style=" fill:#000000;"><g fill="none" fill-rule="nonzero" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="none" font-weight="none" font-size="none" text-anchor="none" style="mix-blend-mode: normal"><path d="M0,172v-172h172v172z" fill="none"></path><g fill="#e74c3c"><path d="M18.87987,153.12013c2.23887,2.23819 5.86807,2.23819 8.10693,0l59.0132,-59.0132l59.0132,59.0132c2.24964,2.17277 5.82555,2.1417 8.03709,-0.06984c2.21154,-2.21154 2.24261,-5.78745 0.06984,-8.03709l-59.0132,-59.0132l59.0132,-59.0132c1.49042,-1.43949 2.08815,-3.57117 1.56346,-5.57571c-0.52469,-2.00454 -2.09015,-3.57 -4.09469,-4.09469c-2.00454,-0.52469 -4.13622,0.07305 -5.57571,1.56346l-59.0132,59.0132l-59.0132,-59.0132c-2.24964,-2.17277 -5.82555,-2.1417 -8.03709,0.06984c-2.21154,2.21154 -2.24261,5.78745 -0.06984,8.03709l59.0132,59.0132l-59.0132,59.0132c-2.23819,2.23887 -2.23819,5.86807 0,8.10693z"></path></g></g></svg>
</div>
</div>
<div class="col-auto bg-master-lightest padding-20 d-none d-sm-inline hide">
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"
width="20" height="20"
viewBox="0 0 172 172"
style=" fill:#000000;"><g fill="none" fill-rule="nonzero" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="none" font-weight="none" font-size="none" text-anchor="none" style="mix-blend-mode: normal"><path d="M0,172v-172h172v172z" fill="none"></path><g fill="#cccccc"><path d="M17.2,37.84c-5.65719,0 -10.32,4.66281 -10.32,10.32v75.68c0,5.65719 4.66281,10.32 10.32,10.32h101.38594c4.31344,0 8.47906,-1.6125 11.65031,-4.54187l0.14781,-0.13438l31.86031,-36.34844l-0.14781,0.16125c4.00437,-4.00438 4.00437,-10.58875 0,-14.59313l0.16125,0.16125l-31.87375,-36.34844l-0.14781,-0.13437c-3.17125,-2.91594 -7.33687,-4.54188 -11.65031,-4.54188zM17.2,44.72h101.38594c2.58,0 5.0525,0.98094 6.96063,2.70094l31.605,36.06625l0.08062,0.08063c1.37063,1.37062 1.37063,3.49375 0,4.86437l-0.08062,0.08063l-31.605,36.05281c-1.90813,1.73344 -4.38063,2.71437 -6.96063,2.71437h-101.38594c-1.935,0 -3.44,-1.505 -3.44,-3.44v-75.68c0,-1.94844 1.49156,-3.44 3.44,-3.44zM127.28,72.24c-7.56531,0 -13.76,6.19469 -13.76,13.76c0,7.56531 6.19469,13.76 13.76,13.76c7.56531,0 13.76,-6.19469 13.76,-13.76c0,-7.56531 -6.19469,-13.76 -13.76,-13.76zM127.28,79.12c3.84313,0 6.88,3.03688 6.88,6.88c0,3.84313 -3.03687,6.88 -6.88,6.88c-3.84312,0 -6.88,-3.03687 -6.88,-6.88c0,-3.84312 3.03688,-6.88 6.88,-6.88z"></path></g></g></svg>
</div>
<div class="col">
<div class="row">
<div class="col">
<p class="no-margin bold fs-12">{{product.description}}</p>
</div>
</div>
<div class="row">
<div class="col">
<p class="muted m-b-0">{{product.stockCode}}</p>
</div>
</div>
</div>
<div class="col-12 col-md-7 mt-2 mt-md-0">
<div class="row align-items-center">
<div class="col-auto">
<p class="m-b-0 small muted">Unit Price</p>
<p class="m-b-0 bold">{{product.unit_price}}</p>
</div>
<div class="col-auto text-center">
<p class="m-b-0 small muted">Quantity</p>
<p class="m-b-0 bold">{{product.quantity}}</p>
</div>
<div class="col text-right">
<p class="m-b-0 small muted">Total</p>
<p class="m-b-0 bold text-success">{{currency}} {{(Math.round((productTotal + Number.EPSILON) * 100) / 100).toFixed(2)}}</p>
<p class="m-b-0 text-complete text-underline pointer" v-if="editable" @click="isEdit = !isEdit">Edit this item?</p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row" v-if="isEdit">
<div class="col padding-25 bg-master-lightest">
<div class="row">
<div class="col-4 p-r-5">
<div class="form-group form-group-default b-rad-none">
<label>Stock Code</label>
<input type="text" class="form-control b-rad-none" v-model="product.stockCode" />
</div>
</div>
<div class="col p-l-5">
<div class="form-group form-group-default b-rad-none required">
<label>description</label>
<input class="form-control b-rad-none" rows="1" @keyup="onlyEnglish($event)" v-model="product.description">
</div>
</div>
</div>
<div class="row align-items-center">
<div class="col-6 p-r-5">
<div class="form-group form-group-default b-rad-none required">
<label>Unit Price</label>
<input type="text" class="form-control b-rad-none" placeholder="Unit Price" v-model.lazy="product.unit_price" v-money="productPrice" />
</div>
</div>
<div class="col-6 p-l-5">
<div class="form-group form-group-default b-rad-none no-padding no-border">
<div class="row no-margin">
<div class="col-auto bg-master-lighter pointer" @mousedown="updateQuantity" @mouseleave="clearInterval" @mouseup="clearInterval" @touchstart="updateQuantity" @touchend="clearInterval" @touchcancel="clearInterval">
<div class="row h-100 align-items-center">
<div class="col">
<i class="fa fa-minus"></i>
</div>
</div>
</div>
<div class="col no-padding">
<label class="p-t-5 p-l-5 text-center">Quantity</label>
<input type="text" class="form-control m-b-5 b-rad-none no-border text-center" v-model.lazy="product.quantity" v-mask="'#########'"/>
</div>
<div class="col-auto bg-master-lighter pointer" @mousedown="updateQuantity('add')" @mouseleave="clearInterval" @mouseup="clearInterval" @touchstart="updateQuantity('add')" @touchend="clearInterval" @touchcancel="clearInterval">
<div class="row h-100 align-items-center">
<div class="col">
<i class="fa fa-plus"></i>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-5">
<p class="m-b-0 small">Total</p>
<h6 class="no-margin bold text-complete">{{currency}} {{productTotal.toFixed(3)}}</h6>
</div>
<div class="col text-right">
<button class="btn btn-lg btn-outline-success b-rad-none" @click="updateProduct()">Save Changes</button>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
@@ -70,6 +152,15 @@
},
},
methods: {
updateQuantity(type){
if(!this.interval){
this.interval = setInterval(() => type === 'add' ? this.product.quantity++ : this.product.quantity > 1 ? this.product.quantity--:null , 80)
}
},
clearInterval(){
clearInterval(this.interval);
this.interval = false;
},
updateProduct(){
this.isEdit = !this.isEdit;
@@ -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>
File diff suppressed because one or more lines are too long
@@ -7,8 +7,8 @@
<div class="col-12 col-md-7">
<div class="row m-b-15">
<div class="col">
<div class="row">
<div class="col-8 p-r-0">
<div class="row m-b-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">
@@ -41,7 +41,42 @@
</div>
</div>
</div>
<div class="col-4 p-r-0">
</div>
<div class="row">
<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">
{{selectedService.name}}
</div>
<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': !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-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="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">{{service.name}}</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<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">
@@ -79,7 +114,7 @@
</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,19 +178,33 @@
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;
this.selectedSupplier.status = false;
this.updateCurrency(supplier.currencies[0]);
},
updateCurrency(currency){
if(currency !== this.selectedCurrency){
this.selectedCurrency = currency;
this.$refs.pendingOrdersList.updateFilters({per_page: 10000, status: 2, type: 1, original_currency_id_in: [this.selectedCurrency.id]});
if(supplier !== this.selectedSupplier){
this.selectedSupplier= supplier;
this.updateList();
}
},
updateService(service){
if(service !== this.selectedService){
this.selectedService = service;
this.updateList();
}
},
updateCurrency(currecny){
if(currecny !== this.selectedCurrency){
this.selectedCurrency = currecny;
this.updateList();
}
},
updateList(){
this.$refs.pendingOrdersList.updateFilters({per_page: 10000, status: 2, type: 1, original_currency_id_in: [this.selectedCurrency.id], transaction_service_id: this.selectedService.id});
this.selectedSupplier.status = false;
this.currencyDropdownLaunch.status = false;
this.serviceDropdownLaunch.status = false;
this.payments = [];
},
@@ -42,16 +42,28 @@
</div>
</div>
</div>
<div class="row m-b-15" v-if="item.owner.type === 1">
<div class="row m-b-15">
<div class="col">
<div class="row m-b-5">
<div class="col">
<div class="fs-8 all-caps muted">Company Name</div>
</div>
</div>
<div class="row">
<div class="row" v-if="isEditCompanyName === false">
<div class="col">
<div class="fs-11 text-primary">{{item.owner.name}}</div>
<div class="fs-11 text-primary">{{item.owner.name}} <i class="fa fa-edit pointer fa-fw m-l-5" v-if="$store.getters.isSuperAdmin" @click="isEditCompanyName = !isEditCompanyName"></i></div>
</div>
</div>
<div class="row" v-if="isEditCompanyName === true">
<div class="col">
<update-company-name-form-component :section="section" :data="item.owner" v-on:submit="isEditCompanyName=false"></update-company-name-form-component>
</div>
<div class="col-auto d-flex align-items-center">
<div class="row">
<div class="col b-none btn btn-sm btn-danger" @click="isEditCompanyName = !isEditCompanyName">
<i class="fa fa-times"></i>
</div>
</div>
</div>
</div>
</div>
@@ -63,9 +75,21 @@
<div class="fs-8 all-caps muted">{{ item.owner.type === 0 ? 'IC' : 'SSM Registration' }} Number</div>
</div>
</div>
<div class="row">
<div class="row" v-if="isEditIdentificationNumber === false">
<div class="col">
<div class="fs-11 text-primary bold">{{item.reference}}</div>
<div class="fs-11 text-primary bold">{{item.reference}} <i class="fa fa-edit pointer fa-fw m-l-5" v-if="$store.getters.isSuperAdmin" @click="isEditIdentificationNumber = !isEditIdentificationNumber"></i></div>
</div>
</div>
<div class="row" v-if="isEditIdentificationNumber === true">
<div class="col">
<update-identification-number-form-component :section="section" :data="{identification_number: item.reference}" :id="item.id" v-on:submit="isEditIdentificationNumber=false"></update-identification-number-form-component>
</div>
<div class="col-auto d-flex align-items-center">
<div class="row">
<div class="col b-none btn btn-sm btn-danger" @click="isEditIdentificationNumber = !isEditIdentificationNumber">
<i class="fa fa-times"></i>
</div>
</div>
</div>
</div>
</div>
@@ -168,7 +192,9 @@
export default {
data() {
return {
expanded: false
expanded: false,
isEditIdentificationNumber: false,
isEditCompanyName: false,
}
},
methods: {
@@ -0,0 +1,38 @@
<template>
<div class="row">
<div class="col p-r-0">
<validation-wrapper-component :validator="$v.parameters.name">
<input type="text" class="form-control fs-12" placeholder="Edit company name" v-model.trim="parameters.name">
</validation-wrapper-component>
</div>
<div class="col-auto bg-success d-flex justify-content-center align-items-center pointer text-white">
<i class="fa fa-check" @click="submitForm"></i>
</div>
</div>
</template>
<script>
import modalFormHandler from '../../../general/mixins/modalFormHandler';
import { required } from "vuelidate/lib/validators";
export default {
data() {
return {
name: this.data.name,
};
},
validations: {
parameters: {
name: { required },
}
},
methods: {
submitForm() {
this.parameters.name = this.data.name;
this.submit(this.route('api.company.update', this.data.id), 'put', '', false, false);
this.$emit('submit');
}
},
mixins: [modalFormHandler]
}
</script>
@@ -0,0 +1,49 @@
<template>
<div class="row">
<div class="col p-r-0">
<validation-wrapper-component :validator="$v.parameters.identification_number">
<input type="text" class="form-control fs-12" placeholder="Edit identification number" v-model.trim="parameters.identification_number">
</validation-wrapper-component>
</div>
<div class="col-auto bg-success d-flex justify-content-center align-items-center pointer text-white">
<i class="fa fa-check" @click="submitForm"></i>
</div>
</div>
</template>
<script>
import modalFormHandler from '../../../general/mixins/modalFormHandler';
import { required } from "vuelidate/lib/validators";
export default {
props: {
id: {
type: Number,
required: true
}
},
data() {
return {
parameters: {
identification_number: this.identification_number,
},
};
},
validations: {
parameters: {
identification_number: { required },
}
},
created() {
if (this.data) {
this.parameters.identification_number = this.data.identification_number
}
},
methods: {
submitForm() {
this.submit(this.route('api.document.reference.update', this.id), 'put', '', false, false);
this.$emit('submit')
}
},
mixins: [modalFormHandler]
}
</script>
File diff suppressed because one or more lines are too long
@@ -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" :creditable=true></wallet-component>
</div>
</div>
<booking-form-component :data="company" section="customerProfileSection"></booking-form-component>
</div>
</div>
File diff suppressed because one or more lines are too long
@@ -42,6 +42,8 @@
}).join(': ')
};
});
this.$store.dispatch('updateListQueue', {name: 'original_'+this.section});
this.$store.dispatch('completeList', {name: 'original_'+this.section, data: response.payload.data});
this.$store.dispatch('completeList', {name: this.section, data: mappedList})
@@ -75,11 +75,9 @@
</div>
<div class="row">
<div class="col-4 p-l-5 p-r-5 m-b-10" v-for="(rate, method) in item.rates">
<!-- <validation-wrapper-component :validator="$v.parameters.currencies.$each[index].rates.$each[method].selling.value" :class="[{'hint-text': rate.payment_method === 'wallet' || rate.payment_method === 'payment gateway'}]"> -->
<validation-wrapper-component :validator="$v.parameters.currencies.$each[index].rates.$each[method].selling.value" :class="[{'hint-text': rate.payment_method === 'wallet'}]">
<validation-wrapper-component :validator="$v.parameters.currencies.$each[index].rates.$each[method].selling.value">
<label class="all-caps">{{rate.payment_method}}</label>
<!-- <input type="text" class="form-control" v-model.lazy="rate.selling.value" v-money="exchangeRate" :disabled="!item.active || rate.payment_method === 'wallet' || rate.payment_method === 'payment gateway'"> -->
<input type="text" class="form-control" v-model.lazy="rate.selling.value" v-money="exchangeRate" :disabled="!item.active || rate.payment_method === 'wallet'">
<input type="text" class="form-control" v-model.lazy="rate.selling.value" v-money="exchangeRate" :disabled="!item.active">
</validation-wrapper-component>
</div>
</div>
@@ -0,0 +1,151 @@
<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">
<div class="col">
<div class="row padding-10">
<div class="col-3 fs-10">Date</div>
<div class="col fs-10">Description</div>
<div class="col-2 fs-10 text-center">Incoming</div>
<div class="col-2 fs-10 text-center">Outgoing</div>
<div class="col-2 fs-10 text-right">Balance</div>
</div>
<div class="row bg-white padding-10 m-b-10 rounded" v-for="(item, index) in company.wallet.transactions" v-bind:key="item.id" :data="item">
<div class="col-3 fs-12">{{item.created_at}}</div>
<div class="col fs-12" v-html="item.description"></div>
<div class="col-2 text-success text-center">{{[5, 9].includes(parseFloat(item.type)) ? (Math.round((parseFloat(item.amount) + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") : ''}}</div>
<div class="col-2 text-danger text-center">{{[1, 11].includes(parseFloat(item.type)) ? '- ' + (Math.round((parseFloat(item.amount) + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") : ''}}</div>
<div class="col-2 text-right">{{remainingBalance(index)}}</div>
</div>
</div>
</div>
<div class="row align-items-center justify-content-center p-t-50 p-b-50" v-if="!company.wallet || !company.wallet.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" :creditable=true></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">
<div class="col">
<wallet-top-up-history-component v-for="item in company.wallet.top_up_records" 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 || !company.wallet.top_up_records.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)
},
remainingBalance(index) {
let tempBalance = 0;
if(this.company.wallet){
let transactions = this.company.wallet.transactions.slice().reverse();
transactions.slice(0, transactions.length - index).map(function(transaction) {
[1, 11].includes(transaction.type) ? tempBalance -= (transaction.amount) : tempBalance += (transaction.amount);
return tempBalance
}, 0);
}
return (Math.round((tempBalance + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
},
successHandler(response){
this.isLoading = false;
this.company = response.payload.data;
}
}
}
</script>
@@ -0,0 +1,63 @@
<template>
<div class="row">
<div class="col">
<div class="row" v-if="!reload">
<div class="col">
<div class="bg-complete" :class="[{'padding-25': !mini}, {'padding-15': mini}]">
<div class="row align-items-end">
<div class="col-auto">
<div class="text-primary-lighter fs-10 text-uppercase">Wallet Balance</div>
<h5 class="text-white no-margin bold">MYR {{ data.wallet ? (Math.round((data.wallet.amount + Number.EPSILON) * 100) / 100).toFixed(2) : '0.00'}}</h5>
</div>
</div>
<div class="row m-t-10 d-flex align-items-center">
<div class="col-auto">
<div class="btn btn-xs p-l-15 p-r-20 b-rad-none font-heading btn-rounded bg-white" @click="reload = true"><i class="fa fa-plus fs-8 m-r-5"></i> Reload</div>
</div>
<div class="col-auto p-l-0" v-if="!mini">
<a class="text-white fs-10" :href="route('wallet.details', data.reference)" target="_blank">Transaction History<i class="fa fa-angle-right p-l-5"></i></a>
</div>
</div>
</div>
</div>
</div>
<div class="row no-margin" v-if="reload">
<div class="col rounded bg-white p-b-15">
<div class="row m-b-15">
<div class="col p-t-15 p-b-15 bg-complete">
<label class="fs-10 text-white m-b-0 text-uppercase cursor" @click="reload = false"><i class="fa fa-angle-left p-r-15"></i>Top Up Wallet</label>
</div>
</div>
<wallet-top-up-form-component :data="data" :amount="(!data.wallet ? amount : (Math.round((((amount - data.wallet.amount) < '0.00' ? '0.00' : (amount - data.wallet.amount)) + Number.EPSILON) * 100) / 100).toFixed(2))" :creditable="creditable"></wallet-top-up-form-component>
</div>
</div>
</div>
</div>
</template>
<script>
import componentHandler from '../../../general/mixins/componentHandler';
export default {
props: {
mini : {
type: Boolean,
default: false
},
amount: {
type: String,
default: '0.00'
},
creditable: {
type: Boolean,
default: false
}
},
data(){
return {
reload: false,
}
},
mixins: [componentHandler],
}
</script>
@@ -0,0 +1,141 @@
<template>
<div class="row">
<div class="col">
<div class="row" v-if="item.status === 1">
<div class="col">
<div class="row m-l-0 m-b-10 m-r-0 parentContainer" >
<div class="col">
<div class="row">
<div class="col">
<div class="row">
<div class="col p-t-10 p-b-10 p-r-0 bg-master-lighter">
<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 text-complete">Pending 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">
<div class="col">
<div class="font-heading fs-8 all-caps" >Submitted On: {{ item.updated_at }}</div>
</div>
</div>
</div>
<div class="col-auto bg-master-light">
<div class="row align-items-center h-100">
<div class="col">
<i class="fa fa-cloud-download muted"></i>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row" v-if="item.status === 2">
<div class="col">
<div class="row m-l-0 m-b-10 m-r-0 parentContainer" >
<div class="col">
<div class="row">
<div class="col">
<div class="row">
<div class="col p-t-10 p-b-10 p-r-0 bg-white">
<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 text-success">Approved</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">
<div class="col">
<div class="font-heading fs-8 all-caps" >Paid On: {{ item.updated_at }}</div>
</div>
</div>
</div>
<div class="col-auto pointer bg-success">
<a :href="route('billplz.bill', item.reference)" target="_blank">
<div class="row align-items-center h-100">
<div class="col">
<i class="fa fa-cloud-download text-white"></i>
</div>
</div>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row" v-if="item.status === 4">
<div class="col">
<div class="row m-l-0 m-b-10 m-r-0 parentContainer b-a b-danger" >
<div class="col">
<div class="row">
<div class="col">
<div class="row">
<div class="col p-t-10 p-b-10 p-r-0">
<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 text-danger">
Rejected
</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">
<div class="col">
<div class="font-heading fs-8 all-caps" >Rejected On: {{ item.updated_at }}</div>
</div>
</div>
</div>
<div class="col-auto">
<div class="row align-items-center h-100">
<div class="col">
<i class="fa fa-ban text-danger"></i>
</div>
</div>
</div>
</div>
</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,152 @@
<template>
<div class="row">
<div class="col">
<div class="row m-b-20 text-center" v-if="$store.getters.isSuperAdmin && creditable">
<div class="col">
<div class="row">
<div class="col p-r-5">
<div class="b-a b-grey bg-white p-t-20 p-b-20 p-l-45 p-r-45 pointer" :class="{ 'bg-success': parameters.transaction_type === 1, 'text-white': parameters.transaction_type === 1, 'b-grey': parameters.transaction_type !== 1 }" @click="parameters.transaction_type !== 1 ? parameters.transaction_type = 1 : parameters.transaction_type = 0">
<p class="no-margin bold">Credit</p>
</div>
</div>
<div class="col p-l-5">
<div class="b-a b-grey bg-white p-t-20 p-b-20 p-l-45 p-r-45 pointer" :class="{ 'bg-danger': parameters.transaction_type === 2, 'text-white': parameters.transaction_type === 2, 'b-grey': parameters.transaction_type !== 2 }" @click="parameters.transaction_type !== 2 ? parameters.transaction_type = 2 : parameters.transaction_type = 0">
<p class="no-margin bold">Debit</p>
</div>
</div>
</div>
<div class="row m-t-10" v-if="parameters.transaction_type !== 0">
<div class="col text-left">
<validation-wrapper-component :validator="$v.parameters.reference">
<label>Reference</label>
<input class="form-control" v-model="parameters.reference">
</validation-wrapper-component>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.amount">
<label>{{parameters.transaction_type == '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 m-l-0 m-r-0">
<div class="col p-l-0 p-r-5">
<div class="btn btn-block btn-sm b-rad-none p-t-10 p-b-10 lh-15" @click="parameters.amount = '500.00'" :class="[{'btn-complete': parseInt(parameters.amount.replace(/\,/g,'')) === 500}, {'btn-default': parseInt(parameters.amount.replace(/\,/g,'')) !== 500}]">MYR<br>500</div>
</div>
<div class="col p-l-5 p-r-5">
<div class="btn btn-block btn-sm b-rad-none p-t-10 p-b-10 lh-15" @click="parameters.amount = '1000.00'" :class="[{'btn-complete': parseInt(parameters.amount.replace(/\,/g,'')) === 1000}, {'btn-default': parseInt(parameters.amount.replace(/\,/g,'')) !== 1000}]">MYR<br>1,000</div>
</div>
<div class="col p-l-5 p-r-0">
<div class="btn btn-block btn-sm b-rad-none p-t-10 p-b-10 lh-15" @click="parameters.amount = '3000.00'" :class="[{'btn-complete': parseInt(parameters.amount.replace(/\,/g,'')) === 3000}, {'btn-default': parseInt(parameters.amount.replace(/\,/g,'')) !== 3000}]">MYR<br>3,000</div>
</div>
</div>
<div class="row m-t-10 m-l-0 m-r-0">
<div class="col p-l-0 p-r-5">
<div class="btn btn-block btn-sm b-rad-none p-t-10 p-b-10 lh-15" @click="parameters.amount = '5000.00'" :class="[{'btn-complete': parseInt(parameters.amount.replace(/\,/g,'')) === 5000}, {'btn-default': parseInt(parameters.amount.replace(/\,/g,'')) !== 5000}]">MYR<br>5,000</div>
</div>
<div class="col p-l-5 p-r-5">
<div class="btn btn-block btn-sm b-rad-none p-t-10 p-b-10 lh-15" @click="parameters.amount = '10000.00'" :class="[{'btn-complete': parseInt(parameters.amount.replace(/\,/g,'')) === 10000}, {'btn-default': parseInt(parameters.amount.replace(/\,/g,'')) !== 10000}]">MYR<br>10,000</div>
</div>
<div class="col p-l-5 p-r-0">
<div class="btn btn-block btn-sm b-rad-none p-t-10 p-b-10 lh-15" @click="parameters.amount = '50000.00'" :class="[{'btn-complete': parseInt(parameters.amount.replace(/\,/g,'')) === 50000}, {'btn-default': parseInt(parameters.amount.replace(/\,/g,'')) !== 50000}]">MYR<br>50,000</div>
</div>
</div>
<div class="row m-t-15 justify-content-center parentContainer" v-if="parseInt(parameters.amount.replace(/\,/g,'')) > 0" >
<div class="col-10">
<div class="btn btn-sm btn-complete btn-block b-rad-none requestModal" data-type="paymentSummary">Reload Credit</div>
</div>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="paymentSummary">
<loading-component style="height: 200px; top: 0;" key="1" color="success" v-show="isLoading"></loading-component>
<div class="row" v-show="!isLoading">
<div class="col bg-white padding-25">
<div class="row m-b-20">
<div class="col">
<div class="font-heading fs-11">You will be redirected to your bank to complete the payment of <span class="text-success bold">{{parameters.amount}} MYR</span> for wallet credit top up. After clicking on the confirm button below. please follow your bank instruction to complete the payment</div>
</div>
</div>
<div class="row m-b-5">
<div class="col">
<button class="btn btn-sm all-caps b-rad-none btn-default bg-master-lighter" data-dismiss="modal">Cancel</button>
</div>
<div class="col-auto">
<button class="btn btn-sm all-caps b-rad-none btn-success" @click="submitForm()">Confirm & Proceed</button>
</div>
</div>
</div>
</div>
</modal-component>
</div>
</div>
</div>
</template>
<script>
import componentHandler from '../../../general/mixins/componentHandler';
import {VMoney} from 'v-money'
import { required, requiredIf, minValue} from "vuelidate/lib/validators";
export default {
props: {
amount: {
type: String,
default: '0.00'
},
creditable: {
type: Boolean,
default: false
}
},
data(){
return {
isLoading: false,
parameters: {
company_id: this.data.id,
amount: '0.00',
transaction_type: 0,
reference: ''
}
}
},
created(){
this.parameters.amount = this.amount
},
validations () {
return {
parameters: {
amount: {
required,
minValue: 10.000,
},
reference: {
required: requiredIf(function () { return this.parameters.transaction_type !== 0 })
}
}
}
},
methods: {
successHandler(response){
if (this.parameters.transaction_type === 0) {
window.location.href = this.route('billplz.bill', response.payload.data.reference) + '?auto_submit=true';
return;
}
location.reload();
},
submitForm() {
this.isLoading = true;
if (this.parameters.transaction_type !== 0 && this.creditable) {
this.submit(this.route('api.wallet.credit'), 'post', '', true, true);
return;
}
this.submit(this.route('api.wallet.topup'), 'post', '', true, true);
}
},
mixins: [componentHandler],
directives: {money: VMoney}
}
</script>
@@ -1,7 +1,7 @@
@extends('layouts.base')
@section('content')
<div class="row d-md-none" v-if="$store.getters.isShowing('sideMenu')">
<div class="row d-md-none" style="display: none;" v-show="$store.getters.isShowing('sideMenu')" >
<div class="col absolute bg-master w-100 h-100" style="opacity: 0.3; z-index: 9998; left: 0px;"></div>
<div class="col-8 bg-master-lightest position-fixed h-100" style="z-index: 9999" >
@include('partials.menu')
@@ -28,16 +28,23 @@
<div class="row m-b-10">
<div class="col">
<h5 class="semi-bold text-success">Your Payment is Successful</h5>
<p class="hint-text">Thank you for your payment. Your transfer request is now being processed and you will be notified once its complete.</p>
<p class="hint-text">Thank you for your payment. {{$transaction->owner instanceof \App\Models\Booking ? 'Your transfer request is now being processed and you will be notified once its complete.' : 'The amount paid has been successfully credited into your wallet.'}}</p>
</div>
</div>
<div class="row m-b-20">
<div class="col">
<a href="{{route('dashboard')}}">
<div class="btn btn-sm all-caps btn-outline-success b-rad-none">Dashboard</div>
</a>
@if($transaction->owner instanceof \App\Models\Booking)
<a href="{{route('dashboard')}}">
<div class="btn btn-sm all-caps btn-outline-success b-rad-none">Dashboard</div>
</a>
@endif
@if($transaction->owner instanceof \App\Models\Wallet)
<a href="{{route('wallet.details', $transaction->owner->owner->reference)}}">
<div class="btn btn-sm all-caps btn-outline-success b-rad-none">Transaction History</div>
</a>
@endif
<a href="{{route('booking.details', $marking)}}">
<div class="btn btn-sm all-caps btn-success b-rad-none" >Back to Booking</div>
<div class="btn btn-sm all-caps btn-success b-rad-none" >{{$transaction->owner instanceof \App\Models\Booking ? 'Back to': 'Last'}} Booking</div>
</a>
</div>
</div>
@@ -58,7 +65,7 @@
<div class="btn btn-sm all-caps btn-outline-success b-rad-none">Dashboard</div>
</a>
<a href="{{route('booking.details', $marking)}}">
<div class="btn btn-sm all-caps btn-success b-rad-none" >Back to Booking</div>
<div class="btn btn-sm all-caps btn-success b-rad-none" >{{$transaction->owner instanceof \App\Models\Booking ? 'Back to': 'Last'}} Booking</div>
</a>
</div>
</div>
@@ -76,9 +83,9 @@
<div class="row m-b-20">
<div class="col">
<a href="{{route('booking.details', $marking)}}">
<div class="btn btn-sm all-caps btn-outline-success b-rad-none" >Back to Booking</div>
<div class="btn btn-sm all-caps btn-outline-success b-rad-none" >{{$transaction->owner instanceof \App\Models\Booking ? 'Back to': 'Last'}} Booking</div>
</a>
<a href="https://www.billplz.com/bills/{{$payment_reference}}">
<a href="{{route('billplz.bill', $transaction->payment_reference)}}">
<div class="btn btn-sm all-caps btn-success b-rad-none">Retry Payment</div>
</a>
@@ -33,12 +33,12 @@
</tr>
@foreach($transactions as $transaction)
<tr style="margin-bottom: 10px;">
<td>{{$transaction->booking->marking}}</td>
<td>{{$transaction->booking->company->reference}}</td>
<td>{{$transaction->owner()->first()->booking->marking}}</td>
<td>{{$transaction->owner()->first()->booking->company->reference}}</td>
<td>{{$transaction->currency_rate}}</td>
<td>{{$transaction->currency->short_code}} {{number_format((float)$transaction->amount, 2, '.', '')}}</td>
<td>Account Holder Name: {{$transaction->booking->bank->holder_name}}<br>{{$transaction->booking->bank->bank_name}}: {{$transaction->booking->bank->account_no}}
<br>Branch: {{$transaction->booking->bank->bank_branch}}<br>Bank in Amount: {{$transaction->original_currency->short_code}} {{$transaction->original_amount}}</td>
<td>Account Holder Name: {{$transaction->owner()->first()->booking->bank->holder_name}}<br>{{$transaction->owner()->first()->booking->bank->bank_name}}: {{$transaction->owner()->first()->booking->bank->account_no}}
<br>Branch: {{$transaction->owner()->first()->booking->bank->bank_branch}}<br>Bank in Amount: {{$transaction->original_currency->short_code}} {{$transaction->original_amount}}</td>
</tr>
@endforeach
</tbody>
@@ -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');
});
+3
View File
@@ -4,6 +4,9 @@ use Illuminate\Support\Facades\Route;
Route::group(['prefix' => 'document', 'as' => 'document.', 'namespace' => 'Documents'], function () {
Route::get('/list', 'ListDocumentsController@list')->name('list');
Route::delete('/{id}/delete', 'DeleteDocumentController@delete')->name('delete');
Route::put('/{id}/approve', 'ApproveDocumentController@approve')->name('status.approve');
Route::put('/{id}/reject', 'RejectDocumentController@reject')->name('status.reject');
Route::put('/{id}/reference/update', 'UpdateDocumentReferenceController@update')->name('reference.update');
});
+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');
+4 -3
View File
@@ -5,8 +5,9 @@ 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('/credit', 'CreditWalletController@credit')->name('credit'); // admin +
Route::put('/{transaction_id}/update-status/{status}', 'UpdateStatusWalletController@updateStatus')->where('status', 'approve|reject')->name('approval');
});
+62 -1
View File
@@ -112,4 +112,65 @@ Route::get('/fix_bills', function () {
});
})->name('products.random');
})->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/{marking}/details', function ($marking) {
$id = \App\Models\Company::where('reference', '=', $marking)->first()->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('billplz/bills/{bill_no}', function($bill_no){
return redirect(env('BILLPLZ_BASE_URL').'/bills/'.$bill_no);
})->name('billplz.bill');
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');