Merge branch 'refund-booking' of gitlab.com:CIEFWorldwideSdnBhd/exchange-2.0 into development

# Conflicts:
#	resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue
This commit is contained in:
JiaSheng
2024-01-15 23:47:57 +08:00
14 changed files with 568 additions and 29 deletions
@@ -0,0 +1,24 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;
class IsNotFullyRefunded implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->withSum(['transactions as total_refund_amount' => function($q) {
$q->refunds()->where('status', ApprovalStatus::APPROVED);
}], 'original_amount')
->having('total_refund_amount', '<', DB::raw('original_amount'));
}
}
@@ -19,6 +19,7 @@ use App\Classes\Modules\Bookings\Services\CalculatesBookingRefundAmount;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject;
use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionRefundCalculationObject;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
class CreateBookingRefundLogic extends AbstractControllerLogic
{
@@ -80,25 +81,30 @@ class CreateBookingRefundLogic extends AbstractControllerLogic
$transaction = $this->fetchesTransaction->execute(['id' => $request->route('payment_id')]);
if ($transaction->transactions()->bills()->first()) {
throw new MalformedRequestException('Booking under white form cannot request for refund');
}
$booking = $transaction->owner;
$billNumber = $this->generatesTransactionBillNumber->execute('RFD-');
$refund = $transaction->transactions()->refunds()->sum('amount');
$refund = $transaction->transactions()->refunds()->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED])->sum('original_amount');
if($refund + $request->input('amount') > $transaction->original_amount) throw new MalformedRequestException('Your refund must not be greater than '. $transaction->original_amount .'.');
$amount = $transaction->booking->fix_currency_id == 1 ? $request->input('amount') : $request->input('amount') / $transaction->currency_rate;
// $transactionRefundCalculationObject = new TransactionRefundCalculationObject($booking, $transaction, $request->input('amount'));
// $transactionRefundCalculationObject->init();
$transactionRefundCalculationObject = new TransactionRefundCalculationObject($booking, $transaction, $amount);
$transactionRefundCalculationObject->init();
$refundAmount = bcdiv($request->input('amount'), $transaction->currency_rate, 7);
// refund service charges if is fully refund
$refundTotal = ($refund + $request->input('amount')) == $transaction->original_amount ? $refundAmount + $transaction->service_charge + $transaction->tax : $refundAmount;
$object = new TransactionObject($billNumber, TransactionType::REFUND, 1, $booking->company->id,
1, $transactionRefundCalculationObject->getConversionObject()->getPaymentMethod(),
$transactionRefundCalculationObject->getRefundTotalAmount(), $transactionRefundCalculationObject->getAmount(), 1,
$transactionRefundCalculationObject->getConversionObject()->getCurrencyId(), $transactionRefundCalculationObject->getTransaction()->currency_rate,
$transactionRefundCalculationObject->getRefundTax(), $transactionRefundCalculationObject->getRefundServiceCharge(), null, ApprovalStatus::PENDING_VERIFICATION, [], $transaction->bill_no);
1, PaymentMethodType::CASH,
$refundTotal, $request->input('amount'), 1,
$transaction->original_currency_id, $transaction->currency_rate,
0, 0, null, ApprovalStatus::PENDING_VERIFICATION, [], $transaction->bill_no);
$transaction = $this->createsTransaction->execute($transaction, $object);
@@ -125,6 +125,8 @@ class ExportsInvoiceTransactions implements FromQuery, WithHeadings, WithHeading
$textToAppend = Carbon::now()->format('[Y-m-d H:i:s]') . ' Shipping Portal Respnose ' . json_encode($row) . PHP_EOL;
file_put_contents($errorFilePath, $textToAppend, FILE_APPEND);
$row = $row[0];
return [
'<<New>>',
Carbon::parse($row['created_at'])->format('m/d/Y H:m'),
@@ -3,6 +3,7 @@
namespace App\Classes\Modules\Transactions\ControllersLogic;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Modules\Transactions\Processors\CreateSupplierTransactionProcessor;
use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber;
use App\Models\Document;
@@ -18,6 +19,7 @@ use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\Modules\Documents\Services\CreatesDocument;
use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject;
use App\Classes\Modules\Transactions\Services\FetchesTransaction;
class CreateSupplierTransactionLogic extends AbstractControllerLogic
{
@@ -48,6 +50,9 @@ class CreateSupplierTransactionLogic extends AbstractControllerLogic
/** @var GeneratesTransactionBillNumber */
private $generatesTransactionBillNumber;
/** @var FetchesTransaction */
private $fetchesTransaction;
/**
* CreateSupplierTransactionLogic constructor.
@@ -56,14 +61,16 @@ class CreateSupplierTransactionLogic extends AbstractControllerLogic
* @param CreatesDocument $createsDocument
* @param CreatesFiles $createsFile
* @param GeneratesTransactionBillNumber $generatesTransactionBillNumber
* @param FetchesTransaction $fetchesTransaction
*/
public function __construct(FetchesCompany $fetchesCompany, CreateSupplierTransactionProcessor $createSupplierTransactionProcessor, CreatesDocument $createsDocument, CreatesFiles $createsFile, GeneratesTransactionBillNumber $generatesTransactionBillNumber)
public function __construct(FetchesCompany $fetchesCompany, CreateSupplierTransactionProcessor $createSupplierTransactionProcessor, CreatesDocument $createsDocument, CreatesFiles $createsFile, GeneratesTransactionBillNumber $generatesTransactionBillNumber, FetchesTransaction $fetchesTransaction)
{
$this->fetchesCompany = $fetchesCompany;
$this->createSupplierTransactionProcessor = $createSupplierTransactionProcessor;
$this->createsDocument = $createsDocument;
$this->createsFile = $createsFile;
$this->generatesTransactionBillNumber = $generatesTransactionBillNumber;
$this->fetchesTransaction = $fetchesTransaction;
}
public function logic(Request $request) : JsonResponse
@@ -75,6 +82,22 @@ class CreateSupplierTransactionLogic extends AbstractControllerLogic
$payments = $request->input('payments');
foreach($payments as $payment){
$payment = $this->fetchesTransaction->execute(['id' => $payment['id']]);
$pendingRefundRequest = $payment->transactions()->refunds()->where('status', ApprovalStatus::PENDING_VERIFICATION)->first();
if ($pendingRefundRequest) {
throw new MalformedRequestException('Unable to create supplier order for pending refund request payment');
}
$totalRefund = $payment->transactions()->refunds()->where('status', ApprovalStatus::APPROVED)->sum('original_amount');
if ($payment->original_amount - $totalRefund <= 0) {
throw new MalformedRequestException('Unable to create supplier order for fully refunded payment');
}
}
$this->createSupplierTransactionProcessor->execute($supplier, $rate, $payments);
if(!count($this->createSupplierTransactionProcessor->getBills())) return $this->response([]);
@@ -73,7 +73,9 @@ class UpdateRefundTransactionStatusLogic extends AbstractControllerLogic
$booking = $transaction->owner->owner;
$reference = 'Credit Voucher for Overpaid for Ref. '.$booking->marking;
$paymentTransaction = $transaction->owner;
$reference = $transaction->amount == $paymentTransaction->amount ? 'Fully Refund for Ref. ' . $booking->marking : 'Partially Refund for Ref. ' . $booking->marking;
if ($transaction->status == ApprovalStatus::APPROVED) {
$this->creditWalletProcessor->execute($booking->company, $transaction->type, $transaction->amount, $reference);
@@ -81,15 +81,19 @@ class CreateSupplierTransactionProcessor
if($payment->status !== ApprovalStatus::APPROVED) continue;
$totalRefund = $payment->transactions()->refunds()->where('status', ApprovalStatus::APPROVED)->sum('original_amount');
$original_amount_after_refund = $payment->original_amount - $totalRefund;
$this->updatesTransactionStatus->execute($payment, ApprovalStatus::COMPLETED);
$billNumber = $this->generatesTransactionBillNumber->execute('SPLR-');
$constant = SegmentConstant::where('reference', SegmentConstants::SERVICE_CHARGE)->where('detail->id', $supplier->id)->first();
$serviceCharge = $this->calculatesTransactionServiceCharge->execute($payment->original_amount, $rate, $constant);
$serviceCharge = $this->calculatesTransactionServiceCharge->execute($original_amount_after_refund, $rate, $constant);
$object = new TransactionObject($billNumber, TransactionType::BILL, $supplier->id, 1,
$supplier->banks()->where('default', true)->first()->id, PaymentMethodType::CASH,
$payment->original_amount * (1 / $rate), $payment->original_amount, 1, $payment->original_currency_id,
$original_amount_after_refund * (1 / $rate), $original_amount_after_refund, 1, $payment->original_currency_id,
$rate, 0, $serviceCharge, null, ApprovalStatus::PENDING_SUBMISSION);
/** @var Transaction $billTransaction */
@@ -101,7 +105,7 @@ class CreateSupplierTransactionProcessor
$transferFee = $this->calculatesTransactionTransferFee->execute($billTransaction->original_amount, $constant);
$object = new TransactionObject($transferFeeNumber, TransactionType::TRANSFER_FEE, 1, $supplier->id,
$supplier->banks()->where('default', true)->first()->id, PaymentMethodType::CASH,
$payment->original_amount, $payment->original_amount, $payment->original_currency_id, $payment->original_currency_id,
$original_amount_after_refund, $original_amount_after_refund, $payment->original_currency_id, $payment->original_currency_id,
1, 0, $transferFee, null, ApprovalStatus::PENDING_VERIFICATION);
$this->pushTransferFee($this->createsTransaction->execute($billTransaction, $object));
@@ -0,0 +1,113 @@
<?php
namespace App\Console\Commands;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Booking;
use Illuminate\Console\Command;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
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\PaymentMethodType;
use App\Models\Transaction;
use Illuminate\Support\Facades\DB;
class AutoFillPurchaseOrderCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'purchaseOrder:autoFill';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Auto fill up the purchase order for booking that have payment';
/** @var GeneratesPurchaseOrderProducts */
private $generatesPurchaseOrderProducts;
/** @var GeneratesTransactionBillNumber */
private $generatesTransactionBillNumber;
/** @var CreatePurchaseOrderTransactionProcessor */
private $createPurchaseOrderTransactionProcessor;
/**
* Create a new command instance.
*
* @return void
*/
public function __construct(GeneratesPurchaseOrderProducts $generatesPurchaseOrderProducts, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatePurchaseOrderTransactionProcessor $createPurchaseOrderTransactionProcessor)
{
parent::__construct();
$this->generatesPurchaseOrderProducts = $generatesPurchaseOrderProducts;
$this->generatesTransactionBillNumber = $generatesTransactionBillNumber;
$this->createPurchaseOrderTransactionProcessor = $createPurchaseOrderTransactionProcessor;
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
// 5. If purchase order not fill up in 2 month, auto fill up it
$bookings = Booking::where('status', ApprovalStatus::APPROVED)
->where('created_at', '<', now()->subDays(60)->endOfDay())
->whereHas('transactions', function($transaction) {
return $transaction->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]);
})
->whereDoesntHave('transactions', function($transaction){
$transaction->where('type', TransactionType::PURCHASE_ORDER);
$transaction->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);
}
}
}
@@ -0,0 +1,98 @@
<?php
namespace App\Console\Commands;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Booking;
use Illuminate\Console\Command;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use App\Classes\Modules\Bookings\Services\UpdatesBookingStatus;
use App\Models\Transaction;
class ExpiredBookingCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'booking:expired';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Expiring booking that do not have further action by user';
/** @var UpdatesBookingStatus */
private $updatesBookingStatus;
/**
* Create a new command instance.
*
* @return void
*/
public function __construct(UpdatesBookingStatus $updatesBookingStatus)
{
parent::__construct();
$this->updatesBookingStatus = $updatesBookingStatus;
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
// 1. Cancel booking without payment & purchase order (1 month)
$bookings = Booking::where('status', ApprovalStatus::APPROVED)
->where('created_at', '<', now()->subDays(30)->endOfDay())
->where(function ($query) {
$query->whereDoesntHave('transactions')
->orWhereDoesntHave('transactions', function($transaction) {
return $transaction->where('type', TransactionType::PURCHASE_ORDER)->orWhere(function ($q) {
$q->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]);
});
});
})->get();
foreach ($bookings as $booking) {
$this->updatesBookingStatus->execute($booking, ApprovalStatus::EXPIRED);
Log::info("Expired Booking without payment & purchase order, booking id: " . $booking->id);
$transactions = $booking->transactions;
foreach ($transactions as $transaction) {
$transaction->status = ApprovalStatus::EXPIRED;
$transaction->save();
Log::info("Expired Transaction id: {$transaction->id} from Booking id: {$booking->id}");
}
}
// 2. Cancel booking without payment but with purchase order (2 month)
$bookings = Booking::where('status', ApprovalStatus::APPROVED)
->where('created_at', '<', now()->subDays(60)->endOfDay())
->where(function ($query) {
$query->whereDoesntHave('transactions', function($transaction) {
return $transaction->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]);
})->whereHas('transactions', function($transaction) {
return $transaction->where('type', TransactionType::PURCHASE_ORDER);
});
})->get();
foreach ($bookings as $booking) {
$this->updatesBookingStatus->execute($booking, ApprovalStatus::EXPIRED);
Log::info("Expired Booking without payment but with purchase order, booking id: " . $booking->id);
$transactions = $booking->transactions;
foreach ($transactions as $transaction) {
$transaction->status = ApprovalStatus::EXPIRED;
$transaction->save();
Log::info("Expired Transaction id: {$transaction->id} from Booking id: {$booking->id}");
}
}
}
}
@@ -0,0 +1,162 @@
<?php
namespace App\Console\Commands;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Booking;
use Illuminate\Console\Command;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use App\Classes\Modules\Bookings\Services\UpdatesBookingStatus;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject;
use App\Classes\Modules\Transactions\Services\CreatesTransaction;
use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Models\Transaction;
class ExpiredRefundedBookingCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'RefundedBooking:expired';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Expiring refunded booking';
/** @var UpdatesBookingStatus */
private $updatesBookingStatus;
/** @var GeneratesTransactionBillNumber */
private $generatesTransactionBillNumber;
/** @var CreatesTransaction */
private $createsTransaction;
/**
* Create a new command instance.
*
* @return void
*/
public function __construct(UpdatesBookingStatus $updatesBookingStatus, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatesTransaction $createsTransaction)
{
parent::__construct();
$this->updatesBookingStatus = $updatesBookingStatus;
$this->generatesTransactionBillNumber = $generatesTransactionBillNumber;
$this->createsTransaction = $createsTransaction;
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
// 3. Cancel fully refunded payment & cancel booking
$transactions = Transaction::where('type', TransactionType::CREDIT_NOTE)->where('payment_reference', 'LIKE', "%refund%")->get();
foreach ($transactions as $transaction) {
// get the booking marking
$payment_reference = explode(" ", trim($transaction->payment_reference));
// $marking = substr($transaction->payment_reference, -5);
$marking = trim(end($payment_reference));
if (!preg_match('/^[0-9]+$/', $marking)) {
$payment_reference = explode(".", trim($transaction->payment_reference));
$marking = trim(end($payment_reference));
}
// for a special payment reference on transaction id: 140231
if (!preg_match('/^[0-9]+$/', $marking)) {
$payment_reference = explode("No", trim($transaction->payment_reference));
$marking = end($payment_reference);
}
// for a special payment reference on transaction id: 152013
if (!preg_match('/^[0-9]+$/', $marking)) {
$payment_reference = explode(" ", trim($transaction->payment_reference));
$marking = end($payment_reference);
$marking = prev($payment_reference);
}
if (preg_match('/^[0-9]+$/', $marking)) {
$booking = Booking::where('marking', $marking)->first();
if ($booking) {
$bookingPayment = $booking->transactions()->payments()->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->first();
if (!$bookingPayment) {
$bookingPaymentCount = $booking->transactions()->payments()->count();
if ($bookingPaymentCount > 1) {
Log::info("Credit note transaction id: {$transaction->id}, there are {$bookingPaymentCount} payment for the booking.");
foreach ($booking->transactions()->payments()->get() as $bp) {
if ($transaction->amount - $bp->amount < 0.01) {
$bookingPayment = $bp;
break;
}
}
}
if (!$bookingPayment) {
$bookingPayment = $booking->transactions()->payments()->whereIn('status', [ApprovalStatus::SUSPENDED, ApprovalStatus::EXPIRED, ApprovalStatus::REJECTED])->orderBy('id', 'DESC')->first();
}
$status = ApprovalStatus::APPROVAL_STATUS_ID[$bookingPayment->status];
Log::info("Credit note transaction id: {$transaction->id}, the payment for the booking is in status {$status}");
}
$bookingPaymentAmount = $bookingPayment->amount;
// check if the booking is fully refund
$amountDifference = bcsub($transaction->amount, $bookingPaymentAmount, 7);
if (abs($amountDifference) < 0.01) {
// rejecting booking payment transaction
// $bookingPayment->status = ApprovalStatus::REJECTED;
// $bookingPayment->save();
//expired booking
// $this->updatesBookingStatus->execute($booking, ApprovalStatus::EXPIRED);
Log::info("Credit note transaction id: {$transaction->id} is fully refunded, the refunded amount was {$transaction->amount} the payment reference is: {$transaction->payment_reference}");
// Log::info("Credit note transaction id: {$transaction->id}, Rejected Booking Transaction Payment id: {$bookingPayment->id}, the payment amount was {$bookingPayment->amount}");
// Log::info("Credit note transaction id: {$transaction->id}, Expired Booking id: {$booking->id}");
} else {
Log::info("Credit note transaction id: {$transaction->id} is not fully refunded, the refunded amount was {$transaction->amount}, the payment amount was {$bookingPayment->amount}, the payment reference is: {$transaction->payment_reference}");
}
$refund = $bookingPayment->transactions()->refunds()->where('amount', $transaction->amount)->where('status', ApprovalStatus::APPROVED)->first();
$bookingInWhiteForm = $bookingPayment->transactions()->bills()->first();
if ($refund) {
Log::info("Credit note transaction id: {$transaction->id}, already created same amount of refund transaction for same booking payment transaction");
}
if ($bookingInWhiteForm) {
Log::info("Credit note transaction id: {$transaction->id}, booking is in white form");
}
if (!$refund && !$bookingInWhiteForm) {
$billNumber = $this->generatesTransactionBillNumber->execute('RFD-');
$object = new TransactionObject($billNumber, TransactionType::REFUND, 1, $booking->company->id,
1, PaymentMethodType::CASH,
$transaction->amount, $transaction->amount * $bookingPayment->currency_rate, 1,
$bookingPayment->original_currency_id, $bookingPayment->currency_rate,
0, 0, null, ApprovalStatus::APPROVED, [], $bookingPayment->bill_no);
$transaction = $this->createsTransaction->execute($bookingPayment, $object);
}
} else {
Log::info("Credit note transaction id: {$transaction->id}, booking marking not found, the payment reference is: {$transaction->payment_reference}");
}
} else {
Log::info("Credit note transaction id: {$transaction->id} does not have booking marking, the payment reference is: {$transaction->payment_reference}");
}
}
}
}
+8
View File
@@ -43,6 +43,14 @@ class Kernel extends ConsoleKernel
->hourly()
->appendOutputTo(storage_path().'/logs/delete-bulk-download-files.log')
->withoutOverlapping();
$schedule->command('booking:expired')
->dailyAt('02:00')
->withoutOverlapping();
$schedule->command('purchaseOrder:autoFill')
->dailyAt('03:00')
->withoutOverlapping();
}
/**
@@ -24,7 +24,7 @@
<div class="col-auto p-l-0" v-if="totalRefunds !== 0">
<div class="font-heading fs-8 muted all-caps">Refunded Amount</div>
<div class="font-heading fs-10 bold text-danger">
{{item.original_currency.short_code}} {{(Math.round((totalRefunds + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
{{item.currency.short_code}} {{(Math.round((totalConvertRefunds + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
</div>
</div>
</div>
@@ -133,7 +133,13 @@
<div class="font-heading all-caps fs-10">Requested Refund Amount</div>
</div>
<div class="col-auto text-right">
<div class="font-heading fs-10">{{item.currency.short_code}} {{(Math.round((totalRequestedRefund + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}</div>
<div class="font-heading fs-10">{{item.original_currency.short_code}} {{(Math.round((totalRequestedRefund + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}</div>
</div>
</div>
<div class="row align-items-end m-b-10 bold text-danger" v-if="totalRequestedRefund != 0">
<div class="col"></div>
<div class="col-auto text-right">
<div class="font-heading fs-10">{{item.currency.short_code}} {{(Math.round((totalRequestedConvertRefund + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}</div>
</div>
</div>
<div class="row align-items-end m-b-10 bold text-danger" v-if="totalRefunds != 0">
@@ -144,6 +150,12 @@
<div class="font-heading fs-12">{{item.original_currency.short_code}} {{(Math.round((totalRefunds + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}</div>
</div>
</div>
<div class="row align-items-end m-b-10 bold text-danger" v-if="totalRefunds != 0">
<div class="col"></div>
<div class="col-auto text-right">
<div class="font-heading fs-12">{{item.currency.short_code}} {{(Math.round((totalConvertRefunds + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}</div>
</div>
</div>
<div class="row align-items-end bold m-b-10 text-primary">
<div class="col">
<div class="font-heading all-caps fs-10">Rate</div>
@@ -187,6 +199,14 @@
<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 align-items-end m-b-10 bold text-success" v-if="totalRefunds != 0">
<div class="col">
<div class="font-heading all-caps fs-10">Your Payment After Refund</div>
</div>
<div class="col-auto text-right">
<div class="font-heading fs-12">MYR {{(Math.round((item.amount - totalConvertRefunds + 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>
@@ -282,14 +302,55 @@
</modal-component>
</div>
</div>
<div class="row m-t-10" v-show="[2, 3].includes(item.status) && totalRequestedConvertRefund < data.booking.amount">
<div class="col">
<button class="btn btn-xs all-caps b-rad-none bg-master-lighter btn-block no-border requestModal hide" data-type="transferSummary">Request Refund</button>
<div class="row m-t-10" v-show="[2, 3].includes(item.status) && (totalRequestedRefund + totalRefunds) < data.booking.amount">
<div class="col" v-if="!item.transaction_bill">
<button class="btn btn-xs all-caps b-rad-none bg-master-lighter btn-block no-border requestModal" data-type="transferSummary">Request Refund</button>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="transferSummary" size="large">
<refund-confirmation-component :data="data" :section="section" :totalRefunds="totalRequestedRefund + totalRefunds"></refund-confirmation-component>
</modal-component>
</div>
</div>
<div class="row m-t-10" v-if="data.transaction_refunds.length > 0">
<div class="col">
<button class="btn btn-xs all-caps b-rad-none bg-master-lighter btn-block no-border" @click="clickExpandRefundTransactions">Show Refund Transactions</button>
</div>
</div>
</div>
</div>
<div class="row" v-if="data.transaction_refunds.length > 0 && expandRefundTransactions">
<div class="col bg-white padding-15">
<div v-for="(refund, index) in data.transaction_refunds">
<div class="row align-items-end m-b-10 bold">
<div class="col">
<div class="font-heading all-caps fs-10">{{ index + 1 }}. Refund updated on</div>
</div>
<div class="col-auto text-right">
<div class="font-heading fs-10">{{ refund.updated_at }}</div>
</div>
</div>
<div class="row align-items-end m-b-10 bold">
<div class="col">
<div class="font-heading all-caps fs-10">&nbsp;&nbsp;&nbsp; Refund status</div>
</div>
<div class="col-auto text-right">
<div class="font-heading fs-10" :class="[{'text-warning': refund.status === 1}, {'text-success': refund.status === 2}, {'text-danger': refund.status === 4}]">{{ refund.status === 1 ? 'Pending Verification' : refund.status === 2 ? 'Approved' : 'Rejected'}}</div>
</div>
</div>
<div class="row align-items-end m-b-10 bold text-danger">
<div class="col">
<div class="font-heading all-caps fs-10">&nbsp;&nbsp;&nbsp; Requested Refund Amount</div>
</div>
<div class="col-auto text-right">
<div class="font-heading fs-10">{{refund.original_currency.short_code}} {{(Math.round((refund.original_amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}</div>
</div>
</div>
<div class="row align-items-end m-b-10 bold text-danger">
<div class="col"></div>
<div class="col-auto text-right">
<div class="font-heading fs-10">{{refund.currency.short_code}} {{(Math.round((refund.amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}</div>
</div>
</div>
</div>
</div>
</div>
</div>
@@ -302,6 +363,7 @@
data(){
return {
expandPaymentDetails: false,
expandRefundTransactions: false,
amount: (Math.round(1000 * 100) / 100).toFixed(2),
parameters: {
amount: (Math.round(1000 * 100) / 100).toFixed(2),
@@ -324,12 +386,12 @@
let vm = this;
var TotalRequestedRefund = 0;
this.data.transaction_refunds.forEach(function(refunds) {
TotalRequestedRefund += refunds.status === 1 ? refunds.original_amount : 0;
TotalRequestedRefund += refunds.status === 1 ? refunds.amount : 0;
});
if (vm.data.booking.fixed_currency.id != 1 && this.data.transaction_refunds[0]) {
TotalRequestedRefund = (TotalRequestedRefund * this.data.transaction_refunds[0].currency_rate);
}
return ((Math.round((TotalRequestedRefund + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","));
// if (vm.data.booking.fixed_currency.id != 1 && this.data.transaction_refunds[0]) {
// TotalRequestedRefund = (TotalRequestedRefund * this.data.transaction_refunds[0].currency_rate);
// }
return TotalRequestedRefund;
},
totalRefunds() {
var TotalRequestedRefund = 0;
@@ -337,11 +399,22 @@
TotalRequestedRefund += refunds.status === 2 ? refunds.original_amount : 0;
});
return TotalRequestedRefund;
},
totalConvertRefunds() {
var TotalRequestedRefund = 0;
this.data.transaction_refunds.forEach(function(refunds) {
TotalRequestedRefund += refunds.status === 2 ? refunds.amount : 0;
});
return TotalRequestedRefund;
}
},
methods: {
clickExpand(){
this.expandPaymentDetails = !this.expandPaymentDetails;
this.expandRefundTransactions = false;
},
clickExpandRefundTransactions(){
this.expandRefundTransactions = !this.expandRefundTransactions;
},
trackShipment(){
window.open(route('booking.track_shipping_order', this.data.booking.marking) + '?token=' + this.$store.getters.getAccessToken, '_blank');
@@ -56,6 +56,16 @@
<span class="flag-icon" :class="'flag-icon-'+item.original_currency.country.short_code.toLowerCase()"></span> {{item.original_currency.short_code}}
</div>
</div>
<div class="col text-right" v-if="totalRefunds !== 0">
<div class="row">
<div class="col">
<div class="font-heading fs-10 muted all-caps">Refunded Amount</div>
<div class="font-heading fs-14 text-danger bold">
{{(Math.round((totalRefunds + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-auto">
@@ -95,7 +105,7 @@
<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.original_amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
{{(Math.round((item.original_amount - totalRefunds + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
</div>
</div>
</div>
@@ -124,11 +134,20 @@
active: false,
}
},
computed: {
totalRefunds() {
var TotalRequestedRefund = 0;
this.data.transaction_refunds.forEach(function(refunds) {
TotalRequestedRefund += refunds.status === 2 ? refunds.original_amount : 0;
});
return TotalRequestedRefund;
}
},
methods: {
activate(){
this.active = !this.active;
this.$emit('input', this.item)
}
},
},
mixins: [componentHandler]
}
@@ -115,7 +115,12 @@
computed: {
total(){
return this.payments.reduce(function (total, currentValue) {
return total + currentValue.original_amount;
return total + currentValue.original_amount - currentValue.transaction_refunds.reduce(function (totalRefund, refundTransaction) {
if (refundTransaction.status === 2) {
return totalRefund + refundTransaction.original_amount;
}
return totalRefund;
}, 0);
}, 0);
},
@@ -117,7 +117,7 @@
</div>
<div class="row">
<div class="col">
<list-component ref="pendingOrdersList" section="pendingOrdersSection" :endpoint="route('api.transaction.list')" :options="{per_page: 5, status: 2, owner_type: 'App\\Models\\Booking', type: 1, original_currency_id_in: [selectedCurrency.id], transaction_service_id: selectedService.id}">
<list-component ref="pendingOrdersList" section="pendingOrdersSection" :endpoint="route('api.transaction.list')" :options="{per_page: 5, status: 2, owner_type: 'App\\Models\\Booking', is_not_fully_refunded: true, type: 1, original_currency_id_in: [selectedCurrency.id], transaction_service_id: selectedService.id}">
<template slot="list" slot-scope="{data}">
<supplier-pending-order-component :data="data" v-on:input="updateOrder($event)"></supplier-pending-order-component>
</template>
@@ -195,7 +195,7 @@
},
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.$refs.pendingOrdersList.updateFilters({per_page: 10000, status: 2, type: 1, is_not_fully_refunded: true, original_currency_id_in: [this.selectedCurrency.id], transaction_service_id: this.selectedService.id});
this.selectedSupplier.status = false;
this.currencyDropdownLaunch.status = false;