Looked into a 504 error order show page

This commit is contained in:
Dillon Ngo
2025-07-06 01:58:16 +08:00
parent 5fef38a04b
commit 71e9a479d9
17 changed files with 301 additions and 890 deletions
@@ -6,8 +6,7 @@ namespace App\Classes\Modules\Orders\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Orders\Services\FetchesOrder;
use App\Classes\Modules\Orders\Standards\Rules\CanFetchOrder;
use App\Http\Resources\OrderShowPageResource;
use App\Http\Resources\OrderV2Resource;
use App\Http\Resources\FetchOrderResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -49,7 +48,6 @@ class FetchOrderV2Logic extends AbstractControllerLogic
*/
public function logic(Request $request) : JsonResponse
{
$this->canFetchOrder->passes();
$query = $this->fetchesOrder->execute(['reference' => $request->route('id'), 'with_packing_lists' => true]);
@@ -57,14 +55,6 @@ class FetchOrderV2Logic extends AbstractControllerLogic
if($request->input('storages')){
$query->storages = $request->input('storages'); //from middleware
}
if($request->route('id') === '578755292')
{
return $this->resourceResponse(new OrderShowPageResource($query));
}
else{
return $this->resourceResponse(new OrderV2Resource($query));
}
return $this->resourceResponse(new FetchOrderResource($query));
}
}
@@ -8,7 +8,6 @@ use App\Classes\Modules\Orders\Services\ListsOrders;
use App\Classes\Modules\Orders\Standards\Rules\CanListOrders;
use App\Classes\ValueObjects\Constants\OrderType;
use App\Http\Resources\OrderBaseResource;
use App\Http\Resources\OrderV2Resource;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -65,9 +64,5 @@ class ListOrdersV2Logic extends AbstractControllerLogic
}
return $this->collectionResponse(OrderBaseResource::collection($query));
//return $this->collectionResponse(OrderV2Resource::collection($query));
}
}
@@ -0,0 +1,61 @@
<?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\Standards\Rules\CanFetchTransaction;
use App\Http\Resources\TransactionWithStorageResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class FetchTransactionLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Fetched Transaction',
'message' => 'You have successfully retrieved a Transaction'
];
}
/** @var CanFetchTransaction */
private $canFetchTransaction;
/** @var FetchesTransaction */
private $fetchesTransaction;
/**
* FetchTransactionLogic constructor.
* @param CanFetchTransaction $canFetchTransaction
* @param FetchesTransaction $fetchesTransaction
*/
public function __construct(CanFetchTransaction $canFetchTransaction, FetchesTransaction $fetchesTransaction)
{
$this->canFetchTransaction = $canFetchTransaction;
$this->fetchesTransaction = $fetchesTransaction;
}
/**
* @param Request $request
* @return JsonResponse
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function logic(Request $request) : JsonResponse
{
$this->canFetchTransaction->passes();
$query = $this->fetchesTransaction->execute(['id' => $request->route('transaction_id')]);
if($request->input('storages')){
$query->storages = $request->input('storages'); //from middleware
}
return $this->resourceResponse(new TransactionWithStorageResource($query));
}
}
@@ -17,8 +17,6 @@ use App\Classes\Modules\Transactions\Services\DeletesGroup;
use App\Classes\Modules\Billplzs\Services\DeletesBillplzBill;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionDetailObject;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
@@ -26,7 +24,6 @@ use App\Classes\ValueObjects\Constants\PackageType;
use App\Classes\ValueObjects\Constants\PackingListType;
use App\Classes\ValueObjects\Constants\TaxPercentage;
use App\Classes\ValueObjects\Constants\TransactionDetailType;
use App\Http\Resources\TransactionForOrderShowPageResource;
use App\Http\Resources\TransactionWithStorageResource;
use App\Models\Order;
use App\Models\PackingList;
@@ -166,6 +163,7 @@ class CheckStorageInvoiceTransactionProcessor
/** @var Transaction $invoice_transaction */
foreach ($transactions as $invoice_transaction){
LogHelper::channel('storage_invoices')->info('invoice_transaction bill_no: '. $invoice_transaction->bill_no);
$result = null;
if(!$is_credit_term){
$result = $this->processSingleTransactionOfTypeShippingInvoice($invoice_transaction, $packingList, $order->company_module_id, $eta);
@@ -183,6 +181,7 @@ class CheckStorageInvoiceTransactionProcessor
private function getArrivalDateAtChinaWarehoue($packingList){
if($packingList->type === PackingListType::SHIPPING_PACKING_LIST){
LogHelper::channel('storage_invoices')->info('packingList reference: '.json_encode($packingList->reference));
$receive_packing_list = PackingList::where('reference', $packingList->reference)->where('type', PackingListType::WAREHOUSE_RECEIVE_LIST)->first();
LogHelper::channel('storage_invoices')->info('receive_packing_list: '.json_encode($receive_packing_list->transports));
$transport = $receive_packing_list->transports->first();
@@ -344,7 +343,7 @@ class CheckStorageInvoiceTransactionProcessor
'currentDate' => $dt2->format('Y-m-d H:i:s'),
'cbm' => $cbm,
'pricePerCBM' => $pricePerCBM,
'storageInvoice' => new TransactionForOrderShowPageResource($storageInvoice)
'storageInvoice' => new TransactionWithStorageResource($storageInvoice)
];
return $result;
}
@@ -407,7 +406,7 @@ class CheckStorageInvoiceTransactionProcessor
'currentDate' => $resultCurrentDate,
'cbm' => $cbm,
'pricePerCBM' => $pricePerCBM,
'storageInvoice' => new TransactionForOrderShowPageResource($storageInvoice)
'storageInvoice' => new TransactionWithStorageResource($storageInvoice)
];
return $result;
}
@@ -0,0 +1,39 @@
<?php
namespace App\Classes\Modules\Transactions\Standards\Rules;
use App\Classes\General\Abstracts\AbstractRule;
class CanFetchTransaction extends AbstractRule
{
/**
* @return bool
*/
protected function authorized($object): bool
{
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,19 @@
<?php
namespace App\Http\Controllers\Transactions;
use App\Classes\Modules\Transactions\ControllersLogic\FetchTransactionLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class FetchTransactionController
{
/**
* @param Request $request
* @param FetchTransactionLogic $logic
* @return JsonResponse
*/
public function fetch(Request $request, FetchTransactionLogic $logic): JsonResponse {
return $logic->execute($request);
}
}
+1
View File
@@ -72,6 +72,7 @@ class Kernel extends HttpKernel
'token.check' => \App\Http\Middleware\TokenCheckerMiddleware::class,
'auth.check' => \App\Http\Middleware\CheckAuthorizationMiddleware::class,
'storage.invoice.check.byorder' => \App\Http\Middleware\CheckForStorageInvoiceByOrderId::class,
'storage.invoice.check.bytransaction' => \App\Http\Middleware\CheckForStorageInvoiceByTransactionId::class,
'storage.invoice.check.bytransactions' => \App\Http\Middleware\CheckForStorageInvoiceByTransactions::class,
'storage.invoice.check.bygroup' => \App\Http\Middleware\CheckForStorageInvoiceByGroup::class,
'storage.invoice.check.bypackinglists' => \App\Http\Middleware\CheckForStorageInvoiceByPackingLists::class,
@@ -0,0 +1,47 @@
<?php
namespace App\Http\Middleware;
use Closure;
use App\Classes\Modules\Transactions\Processors\CheckStorageInvoiceTransactionProcessor;
use App\Models\Transaction;
use Illuminate\Http\Request;
use App\Classes\General\LogHelper;
class CheckForStorageInvoiceByTransactionId
{
/** @var CheckStorageInvoiceTransactionProcessor */
private $storageInvoiceTransactionProcessor;
public function __construct(CheckStorageInvoiceTransactionProcessor $storageInvoiceTransactionProcessor)
{
$this->storageInvoiceTransactionProcessor = $storageInvoiceTransactionProcessor;
}
/**
* Handle an incoming request.
*
* @param Request $request
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle(Request $request, Closure $next)
{
$transactionId = $request->route('transaction_id');
LogHelper::channel('storage_invoices')->info('CheckForStorageInvoiceByTransactionId: ' . $transactionId);
$storages = [];
try{
$transaction = Transaction::where('id', $transactionId)->first();
if($transaction){
$storages = $this->storageInvoiceTransactionProcessor->executeShippingTransaction($transaction);
}
} catch (\Exception $exception) {
$storages = [];
}
$request->merge(['storages' => $storages]);
return $next($request);
}
}
@@ -5,10 +5,9 @@ namespace App\Http\Resources;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\OrderRoleTypes;
use App\Classes\ValueObjects\Constants\TransactionType;
use Carbon\Carbon;
use Illuminate\Http\Resources\Json\JsonResource;
class OrderV2Resource extends JsonResource
class FetchOrderResource extends JsonResource
{
/**
* Transform the resource into an array.
@@ -1,43 +0,0 @@
<?php
namespace App\Http\Resources;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\OrderRoleTypes;
use App\Classes\ValueObjects\Constants\TransactionType;
use Illuminate\Http\Resources\Json\JsonResource;
class OrderShowPageResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'reference' => $this->reference,
'reference_contract' => (int) $this->type,
'type' => (int) $this->type,
'status' => (int) $this->status,
'company_module' => new CompanyModuleResource($this->companyModule),
'warehouse' => new CompanyModuleResource($this->orderRoles()->where('role_id', '=', OrderRoleTypes::ORIGIN_WAREHOUSE)->first()->appointee),
'address' => new AddressResource($this->addresses()->where('status', '=', ApprovalStatus::APPROVED)->first()),
'address_change_request' => new AddressResource($this->addressesPendingVerification()->first()),
'invoices' => $this->whenLoaded('packingLists', function() {
$transactions = $this->transactions()->whereNotIn('transactions.status', [0, 1])->whereIn('transactions.type', [TransactionType::SHIPPING_INVOICE, TransactionType::STORAGE_INVOICE])->get();
foreach ($transactions as $transaction) {
$transaction['is_einvoice_applicable'] = $this->companyModule->company->e_invoice === 1;
}
return TransactionForOrderShowPageResource::collection($transactions);
}),
'storages' => $this->storages ? $this->storages : null, //from middleware
'remarks' => RemarkResource::collection($this->remarks),
'supplier_tax_rebate' => SupplierTaxRebateResource::collection($this->supplierTaxRebate),
'created_at' => $this->created_at->format('d-m-Y'),
];
}
}
@@ -1,71 +0,0 @@
<?php
namespace App\Http\Resources;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Models\Group;
use App\Models\PackingList;
use App\Models\Transaction;
use App\Models\Wallet;
use Carbon\Carbon;
use Illuminate\Http\Resources\Json\JsonResource;
class TransactionForOrderShowPageResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
$groupTransactions = null;
if ($this->owner instanceof Transaction) {
// if ($this->owner) {
// if ($this->owner->owner) {
// $order = new OrderResource($this->owner->owner->owner);
// }
// }
} else if (!($this->owner instanceof Transaction) && !($this->owner instanceof Wallet)) {
// if ($this->owner) {
// $order = new OrderResource($this->owner->owner);
// }
} else {
$group = Group::where('reference', $this->payment_reference)->first();
if ($group) {
$groupTransactions = GroupTransactionResource::collection($group->groupTransactions);
}
}
$packingListReference = null;
if ($this->owner instanceof PackingList) {
$packingListReference = $this->owner->reference;
}
return [
'id' => $this->id,
'owner_type' => $this->owner_type,
'documents' => $groupTransactions ? DocumentResource::collection($this->documents->where('status', ApprovalStatus::PENDING_VERIFICATION)) : DocumentResource::collection($this->documents),
'type' => (int) $this->type,
'bill_no' => $this->bill_no,
'amount' => (double) $this->amount,
'payment_method' => (int) $this->payment_method,
'payment_reference' => $this->payment_reference,
'service_charge' => (double) $this->service_charge,
'tax' => (double) $this->tax,
'original_amount' => (double) $this->original_amount,
'currency_rate' => (double) $this->currency_rate,
'status' => (int) $this->status,
'remarks' => RemarkResource::collection($this->remarks),
'packing_list_reference' => $packingListReference,
'storages' => $this->storages ? $this->storages : null, //from middleware
'is_waived' => (int) $this->is_waived,
'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'),
'created_at' => Carbon::parse($this->created_at)->format('d-m-Y'),
'is_einvoice_applicable' => Carbon::parse($this->created_at)->isAfter(Carbon::parse(env('E_INVOICE_START_DATE', '2025-07-01 00:00:00'))) && $this->is_einvoice_applicable,
];
}
}
@@ -149,7 +149,7 @@
</div>
</div>
<div class="row m-b-30" v-if="(order.reference != '578755292') && order.invoices.length">
<!-- <div class="row m-b-30" v-if="(order.reference != '578755292') && order.invoices.length">
<div class="col">
<div class="row m-b-20">
<div class="col">
@@ -166,8 +166,8 @@
</div>
</div>
</div>
</div>
<div class="row m-b-30" v-else>
</div> -->
<div class="row m-b-30" v-if="order.invoices.length">
<div class="col">
<div class="row m-b-20">
<div class="col">
@@ -176,19 +176,13 @@
</div>
</div>
<div class="row bg-master-lightest p-t-15" v-for="invoice in order.invoices" v-if="invoice.type === 1">
<div class="col" v-if="getMergedInvoices(invoice).length > 1">
<cust-pay-bill-with-storage-component :data="getMergedInvoices(invoice)" :storage="getStorageInfo(invoice)" invoice_status="Pending Payment" :section="section"></cust-pay-bill-with-storage-component>
</div>
<div class="col" v-else>
<cust-pay-bill-component :data="invoice" invoice_status="Pending Payment" :section="section"></cust-pay-bill-component>
</div>
<cust-pay-bill-parent-component :data="invoice" :section="section"></cust-pay-bill-parent-component>
</div>
</div>
</div>
</div>
</div>
<order-package-v3-section-component
v-if="!isLoading && showOld"
:order_number="order_number">
@@ -224,16 +218,16 @@
pendingQueue () {
return this.$store.getters.isInCompleteQueue(this.section);
},
orderStorageMap() {
// Create a map to link parent invoice IDs to storageInvoiceIds
const storageMap = {};
if(this.order.storages){
for (const storage of this.order.storages) {
storageMap[storage.parentInvoiceId] = storage.storageInvoiceId;
}
}
return storageMap;
}
// orderStorageMap() {
// // Create a map to link parent invoice IDs to storageInvoiceIds
// const storageMap = {};
// if(this.order.storages){
// for (const storage of this.order.storages) {
// storageMap[storage.parentInvoiceId] = storage.storageInvoiceId;
// }
// }
// return storageMap;
// }
},
watch: {
pendingQueue(inComplete){
@@ -264,35 +258,35 @@
window.location.href = this.route('error.404');
}
},
getStorageInfo(invoice) {
const storageObject = this.findStorageInfoObject(invoice.id);
return storageObject;
},
findStorageInfoObject(shippingInvoiceId) {
if(this.order.storages){
return this.order.storages.find(storage => storage.parentInvoiceId === shippingInvoiceId);
}
return null;
},
getMergedInvoices(invoice){
const storageInvoice = this.getStorageInvoice(invoice);
const mergedArray = [
...(invoice ? [invoice] : []),
...(storageInvoice ? [storageInvoice] : []),
];
return mergedArray;
},
getStorageInvoice(invoice) {
// Retrieve the storageInvoiceId for the current shipping invoice from storage info (order.storages)
const storageInvoiceId = this.orderStorageMap[invoice.id];
// getStorageInfo(invoice) {
// const storageObject = this.findStorageInfoObject(invoice.id);
// return storageObject;
// },
// findStorageInfoObject(shippingInvoiceId) {
// if(this.order.storages){
// return this.order.storages.find(storage => storage.parentInvoiceId === shippingInvoiceId);
// }
// return null;
// },
// getMergedInvoices(invoice){
// const storageInvoice = this.getStorageInvoice(invoice);
// const mergedArray = [
// ...(invoice ? [invoice] : []),
// ...(storageInvoice ? [storageInvoice] : []),
// ];
// return mergedArray;
// },
// getStorageInvoice(invoice) {
// // Retrieve the storageInvoiceId for the current shipping invoice from storage info (order.storages)
// const storageInvoiceId = this.orderStorageMap[invoice.id];
// Find and return the storage invoice (type 16) from order.invoices
const storageInvoice = this.order.invoices.find((invoice) => {
return invoice.type === 16 && invoice.id === storageInvoiceId;
});
// // Find and return the storage invoice (type 16) from order.invoices
// const storageInvoice = this.order.invoices.find((invoice) => {
// return invoice.type === 16 && invoice.id === storageInvoiceId;
// });
return storageInvoice;
},
// return storageInvoice;
// },
download(param) {
let url = route('order.qr.download', param.id);
if(window.LARAVEL_VAPOR_ENABLED){
@@ -1,314 +0,0 @@
<template>
<div class="row m-b-15 m-l-5 m-r-10 parentContainer">
<div class="col bg-white rounded">
<div class="row justify-content-end" v-if="item.type === 1 && $store.getters.isSuperAdmin">
<!-- <div class="btn btn-sm btn block all-caps b-rad-none btn-danger pointer requestModal m-l-20" data-type="deleteInvoice">Delete</div> -->
<span class="d-inline-block m-r-15 text-primary bold text-underline pointer requestModal" data-type="deleteInvoice">
<i class="fa fa-close fa-2x"></i>
</span>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="deleteInvoice">
<delete-invoice-form-component :data="item" :section="section"></delete-invoice-form-component>
</modal-component>
</div>
<div class="row" :class="[{'b-danger': item.status == 5 ||item.status == 6, 'b-a': item.status == 5||item.status == 6}]">
<div class="col">
<div class="row padding-20 align-items-center">
<div class="col-auto">
<p class="no-margin fs-10 all-caps">Invoice Date</p>
<div> {{ item.created_at }}</div>
</div>
<div class="col-auto">
<p class="no-margin fs-10 all-caps">Status</p>
<div class="all-caps" v-if="item.status == 3">Payment Completed</div>
<div class="all-caps text-danger" v-else-if="item.status == 5">Dispute in progress</div>
<div class="all-caps" v-else-if="item.status == 6">Cancelled Invoice</div>
<div class="all-caps" v-else>Pending Payment</div>
</div>
<div class="col-auto">
<p class="no-margin fs-10 all-caps">Amount</p>
<div>MYR {{ item.amount.toFixed(2) }}</div>
</div>
<div class="col" v-if="item.remarks.length">
<p class="no-margin fs-10 all-caps">Billing Question</p>
<div>
{{ latestComment.content }}
<span class="btn requestModal no-border" v-if="item.remarks.length" size="large" data-type="chatmodal">
<i class="fa fa-comment-o"></i>
</span>
</div>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="chatmodal">
<remark-component :section="section" :data="item" module_type="Transaction"></remark-component>
</modal-component>
</div>
<div class="col" v-else>
<p class="no-margin fs-10 all-caps invisible">Billing Question</p>
<div>
<span class="btn requestModal no-border invisible">
<i class="fa fa-edit"></i>
</span>
</div>
</div>
<div class="col-auto">
<div :class="[{'invisible': [5, 6, 3].includes(item.status)}]">
<span class="d-inline-block m-r-15 text-primary bold text-underline pointer requestModal" data-type="billingRemark">Billing Question?</span>
</div>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="billingRemark">
<customer-invoice-remark-form-component module_type="Transaction" :data="item" :section="section"></customer-invoice-remark-form-component>
</modal-component>
</div>
<!-- PDF - INV -->
<div class="col-auto" v-if="!isEinvoiceApplicable">
<div v-if="item.documents.length && item.documents.some(d => d.document_type === 'SHIPPING_INVOICE')">
<div v-for="doc in item.documents.filter(d => d.document_type === 'SHIPPING_INVOICE')" :key="doc.id">
<div v-for="file in doc.files" v-bind:key="file.id" class="col-auto no-padding">
<document-file-viewer-component :file="file">
<template slot="button">
<div class="bg-grey no-border muted">
<svg width="40" height="48" viewBox="0 0 40 48" xmlns="http://www.w3.org/2000/svg">
<path d="M4 0h24l8 8v40a4 4 0 0 1 -4 4H4a4 4 0 0 1 -4 -4V4a4 4 0 0 1 4 -4z" fill="#27ae60"/>
<path d="M28 0v8h8z" fill="#1e8449"/>
<text x="50%" y="60%" text-anchor="middle" fill="white" font-size="13" font-family="Arial, sans-serif" font-weight="bold" dy=".3em">INV</text>
</svg>
</div>
</template>
</document-file-viewer-component>
</div>
</div>
</div>
<div v-else>
<div class="btn bg-grey no-border muted invisible">
<i class="fa fa-file-pdf-o"></i>
</div>
</div>
</div>
<!-- PDF - EINV -->
<div class="col-auto" v-if="isEinvoiceApplicable">
<div v-if="item.documents.length && item.documents.some(d => d.document_type === 'SHIPPING_EINVOICE')">
<div v-for="doc in item.documents.filter(d => d.document_type === 'SHIPPING_EINVOICE')" :key="doc.id">
<div v-for="file in doc.files" v-bind:key="file.id" class="col-auto no-padding">
<document-file-viewer-component :file="file">
<template slot="button">
<div class="bg-grey no-border muted">
<svg width="48" height="48" viewBox="0 0 40 48" xmlns="http://www.w3.org/2000/svg">
<path d="M4 0h24l8 8v40a4 4 0 0 1 -4 4H4a4 4 0 0 1 -4 -4V4a4 4 0 0 1 4 -4z" fill="#27ae60"/>
<path d="M28 0v8h8z" fill="#1e8449"/>
<text x="50%" y="60%" text-anchor="middle" fill="white" font-size="12" font-family="Arial, sans-serif" font-weight="bold" dy=".3em">EINV</text>
</svg>
</div>
</template>
</document-file-viewer-component>
</div>
</div>
</div>
<div v-else>
<!-- <div class="btn bg-grey no-border muted invisible">
<i class="fa fa-file-pdf-o"></i>
</div> -->
<div class="bg-grey no-border muted">
<svg width="48" height="48" viewBox="0 0 40 48" xmlns="http://www.w3.org/2000/svg">
<path d="M4 0h24l8 8v40a4 4 0 0 1 -4 4H4a4 4 0 0 1 -4 -4V4a4 4 0 0 1 4 -4z" fill="#bdc3c7"/>
<path d="M28 0v8h8z" fill="#95a5a6"/>
<text x="50%" y="60%" text-anchor="middle" fill="white" font-size="12" font-family="Arial, sans-serif" font-weight="bold" dy=".3em">EINV</text>
</svg>
</div>
</div>
</div>
<!-- PDF - SO -->
<div class="col-auto">
<div v-if="item.documents.length && item.documents.some(d => d.document_type === 'SALES_ORDER')">
<div v-for="doc in item.documents.filter(d => d.document_type === 'SALES_ORDER')" :key="doc.id">
<div v-for="file in doc.files" v-bind:key="file.id" class="col-auto no-padding">
<document-file-viewer-component :file="file">
<template slot="button">
<div class="bg-grey no-border muted">
<svg width="40" height="48" viewBox="0 0 40 48" xmlns="http://www.w3.org/2000/svg">
<path d="M4 0h24l8 8v40a4 4 0 0 1 -4 4H4a4 4 0 0 1 -4 -4V4a4 4 0 0 1 4 -4z" fill="#27ae60"/>
<path d="M28 0v8h8z" fill="#1e8449"/>
<text x="50%" y="60%" text-anchor="middle" fill="white" font-size="14" font-family="Arial, sans-serif" font-weight="bold" dy=".3em">SO</text>
</svg>
</div>
</template>
</document-file-viewer-component>
</div>
</div>
</div>
<div v-else>
<!-- <div class="btn bg-grey no-border muted invisible">
<i class="fa fa-file-pdf-o"></i>
</div> -->
<div class="bg-grey no-border muted">
<svg width="40" height="48" viewBox="0 0 40 48" xmlns="http://www.w3.org/2000/svg">
<path d="M4 0h24l8 8v40a4 4 0 0 1 -4 4H4a4 4 0 0 1 -4 -4V4a4 4 0 0 1 4 -4z" fill="#bdc3c7"/>
<path d="M28 0v8h8z" fill="#95a5a6"/>
<text x="50%" y="60%" text-anchor="middle" fill="white" font-size="14" font-family="Arial, sans-serif" font-weight="bold" dy=".3em">SO</text>
</svg>
</div>
</div>
</div>
<!-- cief todo: 90 - why hide??? -->
<!-- <div class="col-auto hide">
<div class="btn btn-sm all-caps b-rad-none btn-block" :class="{'btn-success': !expanded, 'btn-default': expanded}" @click="expanded = !expanded">
{{ expanded ? 'Cancel' : 'Make Payment' }}</div>
</div> -->
</div>
</div>
</div>
<div class="row" v-if="$store.getters.isAdmin">
<div class="col">
<div class="row padding-20">
<div class="col">
<p class="no-margin fs-10 all-caps">Packinglist Reference</p>
<div>
<a :href="route('order.tracking', item.packing_list_reference)" target="_blank">
{{ item.packing_list_reference }}
</a>
</div>
</div>
<div class="col-auto d-flex justify-content-center align-items-center" v-if="$store.getters.isSuperAdmin">
<div class="btn btn-sm btn block all-caps b-rad-none btn-danger pointer requestModal m-l-20" data-type="regenerateInvoice" v-if="!isEinvoiceApplicable">Regenerate Invoice PDF</div>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="regenerateInvoice">
<general-confirmation-form-component
contentText="Are you sure you want to regenerate this Invoice PDF document?"
modalType="delete"
buttonText="Regenerate"
class="text-center"
:apiRoute="route('api.transaction.invoice.regenerate', item.id)"
apiMethod="post"
:section="section"
>
</general-confirmation-form-component>
</modal-component>
<div class="btn btn-sm btn block all-caps b-rad-none btn-danger pointer requestModal m-l-20" data-type="regenerateEInvoice" v-if="isEinvoiceApplicable">Regenerate E-Invoice PDF</div>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="regenerateEInvoice">
<general-confirmation-form-component
contentText="Are you sure you want to regenerate this E-Invoice PDF document?"
modalType="delete"
buttonText="Regenerate"
class="text-center"
:apiRoute="route('api.transaction.einvoice.regenerate', item.id)"
apiMethod="post"
:section="section"
>
</general-confirmation-form-component>
</modal-component>
<div class="btn btn-sm btn block all-caps b-rad-none btn-danger pointer requestModal m-l-20" data-type="regenerateSalesOrder">Regenerate Sales Order PDF</div>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="regenerateSalesOrder">
<general-confirmation-form-component
contentText="Are you sure you want to regenerate this Sales Order PDF document?"
modalType="delete"
buttonText="Regenerate"
class="text-center"
:apiRoute="route('api.transaction.sales.order.regenerate', item.id)"
apiMethod="post"
:section="section"
>
</general-confirmation-form-component>
</modal-component>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import componentHandler from '../../../general/mixins/componentHandler';
export default {
props: {
invoice_status: {
type: String,
required: true
},
section:{
type: String,
required: true
},
},
data(){
return {
parameters: {
packing_list_id: null,
transaction_details: [],
},
expanded: true,
showPaymentProceedModal: false,
showPaymentOutdatedModal: false,
isEinvoiceApplicable: this.data.is_einvoice_applicable,
}
},
computed: {
// cbm () {
// return (Math.ceil((this.item.packages.reduce((total, obj) => (obj.type === 2 ? 0 : obj.cbm) + total, 0)) * 1000) / 1000).toFixed(3)
// },
// overweight(){
// return (Math.ceil((this.item.packages.reduce((total, obj) => (obj.type === 2 ? obj.cbm : 0) + total, 0)) * 1000) / 1000).toFixed(3)
// },
latestComment() {
let questions = this.item.remarks;
return questions.slice().reverse()[0];
},
paymentPending(){
if (Array.isArray(this.item.transactions)) {
for (let i = 0; i < this.item.transactions.length; i++) {
const status = this.item.transactions[i].status;
if (status === 1) {
return true;
}
}
}
return false;
}
},
created(){
this.parameters.packing_list_id = this.data.id;
},
methods: {
handleMakePaymentClick(event) {
let selectedShippingInvoicesOnlyIds = [];
this.showPaymentProceedModal = false;
this.showPaymentOutdatedModal = false;
selectedShippingInvoicesOnlyIds.push(this.item.id);
this.submit(this.route('api.transaction.verify.transactions', JSON.stringify(selectedShippingInvoicesOnlyIds)), 'get', 'verifyPaymentForOrderProfileV2Section', false, false);
},
successHandler(response, section){
if(section === "verifyPaymentForOrderProfileV2Section")
{
const totalAmount = response.payload.data.reduce((total, item) => {
const topLevelAmount = item.amount || 0;
const storagesAmount = item.storages ? item.storages.reduce((sum, storage) => {
const storageInvoiceAmount = storage.storageInvoice?.amount || 0;
return sum + storageInvoiceAmount;
}, 0) : 0;
return total + topLevelAmount + storagesAmount;
}, 0);
const epsilon = 0.0001;
if(Math.abs(this.item.outstanding - totalAmount) < epsilon){
this.showPaymentProceedModal = true;
}
else{
this.showPaymentOutdatedModal = true;
}
}
else{
this.item = response.payload.data;
// this.$forceUpdate();
}
},
paymentOutdated(){
this.showPaymentProceedModal = false;
this.showPaymentOutdatedModal = true;
}
},
mixins: [componentHandler]
}
</script>
@@ -0,0 +1,82 @@
<template>
<div class="col">
<loading-component style="height: 200px; top: 0;" v-if="isLoading"></loading-component>
<div class="row flex-wrap" v-if="!isLoading && transaction">
<div class="col" v-if="getMergedInvoices(transaction).length > 1">
<customer-payments-billing-with-storage-component :data="getMergedInvoices(transaction)" :storage="getStorageInfo(transaction)" invoice_status="Pending Payment" :section="section"></customer-payments-billing-with-storage-component>
</div>
<div class="col" v-else>
<customer-payments-billing-component :data="transaction" invoice_status="Pending Payment" :section="section"></customer-payments-billing-component>
</div>
</div>
</div>
</template>
<script>
import componentHandler from '../../../general/mixins/componentHandler';
export default {
data(){
return {
section: 'orderCustomerPaymentBillingSection-' + this.data.id,
isLoading: true,
transaction: null,
storage: null,
}
},
computed: {
pendingQueue () {
return this.$store.getters.isInCompleteQueue(this.section);
},
orderStorageMap() {
// Create a map to link parent invoice IDs to storageInvoiceIds
const storageMap = {};
if(this.transaction.storages){
for (const storage of this.transaction.storages) {
storageMap[storage.parentInvoiceId] = storage.storageInvoiceId;
}
}
return storageMap;
}
},
watch: {
pendingQueue(inComplete){
if(inComplete){
this.fetchTransaction();
}
}
},
created(){
this.$store.dispatch('updateListQueue', {'name': this.section});
},
methods: {
fetchTransaction(){
this.isLoading = true;
this.submit(route('api.transaction.fetch', this.data.id), 'get', this.section, false, false)
},
successHandler(response){
this.$store.dispatch('completeList', {'name': this.section, 'data': []});
this.isLoading = false;
this.transaction = response.payload.data;
this.storage = response.payload.data.storages?.[0] ?? null;
},
getStorageInfo(invoice) {
const storageObject = this.findStorageInfoObject(invoice.id);
return storageObject;
},
findStorageInfoObject(shippingInvoiceId) {
if(this.transaction.storages){
return this.transaction.storages.find(storage => storage.parentInvoiceId === shippingInvoiceId);
}
return null;
},
getMergedInvoices(invoice){
const storageInvoice = this.storage?.storageInvoice ?? null;
const mergedArray = [
...(invoice ? [invoice] : []),
...(storageInvoice ? [storageInvoice] : []),
];
return mergedArray;
},
},
mixins: [componentHandler]
}
</script>
@@ -1,389 +0,0 @@
<template>
<div class="row m-b-15 m-l-5 m-r-10 parentContainer">
<div class="col bg-white rounded">
<div v-for="item in items" class="row" :class="[{'b-danger': item.status == 5 ||item.status == 6, 'b-a': item.status == 5||item.status == 6}]">
<div class="col">
<div class="row justify-content-end" v-if="item.type === 1 && $store.getters.isSuperAdmin">
<!-- <div class="btn btn-sm btn block all-caps b-rad-none btn-danger pointer requestModal m-l-20" :data-type="'deleteInvoice-' + item.id" v-if="item.type === 1">Delete</div> -->
<span class="d-inline-block m-r-15 text-primary bold text-underline pointer requestModal" :data-type="'deleteInvoice-' + item.id">
<i class="fa fa-close fa-2x"></i>
</span>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" :type="'deleteInvoice-' + item.id">
<delete-invoice-form-component :data="item" :section="section"></delete-invoice-form-component>
</modal-component>
</div>
<div class="row padding-20 align-items-center">
<div class="col-auto">
<p class="no-margin fs-10 all-caps">Invoice Date</p>
<div> {{ item.created_at }}</div>
</div>
<div class="col-auto">
<p class="no-margin fs-10 all-caps">Status</p>
<div class="all-caps" v-if="item.status == 3">Payment Completed</div>
<div class="all-caps text-danger" v-else-if="item.status == 5">Dispute in progress</div>
<div class="all-caps" v-else-if="item.status == 6">Cancelled Invoice</div>
<div class="all-caps" v-else>Pending Payment</div>
</div>
<div class="col-auto">
<p class="no-margin fs-10 all-caps">Amount</p>
<div>MYR {{ item.amount.toFixed(2) }}</div>
</div>
<div class="col">
<div v-if="item.remarks.length">
<p class="no-margin fs-10 all-caps">Billing Question</p>
<div>
{{ getLatestComment(item).content }}
<span class="btn requestModal no-border" v-if="item.remarks.length" size="large" data-type="chatmodal">
<i class="fa fa-comment-o"></i>
</span>
</div>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="chatmodal">
<remark-component :section="section" :data="item" module_type="Transaction"></remark-component>
</modal-component>
</div>
<div v-else>
<p class="no-margin fs-10 all-caps invisible">Billing Question</p>
<div>
<span class="btn requestModal no-border invisible">
<i class="fa fa-edit"></i>
</span>
</div>
</div>
</div>
<div class="col-auto">
<div v-if="item.type === 1" :class="[{'invisible': [5, 6, 3].includes(item.status)}]">
<span class="d-inline-block m-r-15 text-primary bold text-underline pointer requestModal" data-type="billingRemark">Billing Question?</span>
</div>
<modal-component v-if="item.type === 1" class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="billingRemark">
<customer-invoice-remark-form-component module_type="Transaction" :data="item" :section="section"></customer-invoice-remark-form-component>
</modal-component>
</div>
<div class="col-auto" v-if="$store.getters.isAdmin">
<span class="d-inline-block m-r-15 text-primary bold text-underline pointer requestModal" v-if="item.type === 16 && item.is_waived === 0 && item.status === 2" :data-type="'waiveInvoice-' + item.id">
Waive Transaction
</span>
<span class="d-inline-block m-r-15 text-primary bold" v-else-if="item.type === 16 && item.is_waived === 1">
Transaction Waived
</span>
<span class="d-inline-block m-r-15 text-primary bold" v-else>
Waive N/A
</span>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" v-if="item.type === 16 && item.is_waived === 0 && item.status === 2" :type="'waiveInvoice-' + item.id">
<waive-invoice-form-component :data="item" :section="section"></waive-invoice-form-component>
</modal-component>
</div>
<!-- PDF - INV: SHIP + STOR -->
<div class="col-auto" v-if="!isEinvoiceApplicable">
<div v-if="item.documents.length && item.documents.some(d => d.document_type === 'SHIPPING_INVOICE' || d.document_type === 'STORAGE_INVOICE')">
<div v-for="doc in item.documents.filter(d => d.document_type === 'SHIPPING_INVOICE' || d.document_type === 'STORAGE_INVOICE')" :key="doc.id">
<div v-for="file in doc.files" v-bind:key="file.id" class="col-auto no-padding">
<document-file-viewer-component :file="file">
<template slot="button">
<div class="bg-grey no-border muted">
<!-- <i class="fa fa-file-pdf-o"></i> -->
<svg width="40" height="48" viewBox="0 0 40 48" xmlns="http://www.w3.org/2000/svg">
<path d="M4 0h24l8 8v40a4 4 0 0 1 -4 4H4a4 4 0 0 1 -4 -4V4a4 4 0 0 1 4 -4z" fill="#27ae60"/>
<path d="M28 0v8h8z" fill="#1e8449"/>
<text x="50%" y="60%" text-anchor="middle" fill="white" font-size="13" font-family="Arial, sans-serif" font-weight="bold" dy=".3em">INV</text>
</svg>
</div>
</template>
</document-file-viewer-component>
</div>
</div>
</div>
<div v-else>
<div class="bg-grey no-border muted invisible">
<!-- <i class="fa fa-file-pdf-o"></i> -->
<svg width="40" height="48" viewBox="0 0 40 48" xmlns="http://www.w3.org/2000/svg">
<path d="M4 0h24l8 8v40a4 4 0 0 1 -4 4H4a4 4 0 0 1 -4 -4V4a4 4 0 0 1 4 -4z" fill="#bdc3c7"/>
<path d="M28 0v8h8z" fill="#95a5a6"/>
<text x="50%" y="60%" text-anchor="middle" fill="white" font-size="13" font-family="Arial, sans-serif" font-weight="bold" dy=".3em">INV</text>
</svg>
</div>
</div>
</div>
<!-- PDF - EINV -->
<div class="col-auto" v-if="isEinvoiceApplicable">
<div v-if="item.documents.length && item.documents.some(d => d.document_type === 'SHIPPING_EINVOICE')">
<div v-for="doc in item.documents.filter(d => d.document_type === 'SHIPPING_EINVOICE')" :key="doc.id">
<div v-for="file in doc.files" v-bind:key="file.id" class="col-auto no-padding">
<document-file-viewer-component :file="file">
<template slot="button">
<div class="bg-grey no-border muted">
<svg width="48" height="48" viewBox="0 0 40 48" xmlns="http://www.w3.org/2000/svg">
<path d="M4 0h24l8 8v40a4 4 0 0 1 -4 4H4a4 4 0 0 1 -4 -4V4a4 4 0 0 1 4 -4z" fill="#27ae60"/>
<path d="M28 0v8h8z" fill="#1e8449"/>
<text x="50%" y="60%" text-anchor="middle" fill="white" font-size="12" font-family="Arial, sans-serif" font-weight="bold" dy=".3em">EINV</text>
</svg>
</div>
</template>
</document-file-viewer-component>
</div>
</div>
</div>
<div v-else>
<div class="bg-grey no-border muted">
<svg width="48" height="48" viewBox="0 0 40 48" xmlns="http://www.w3.org/2000/svg">
<path d="M4 0h24l8 8v40a4 4 0 0 1 -4 4H4a4 4 0 0 1 -4 -4V4a4 4 0 0 1 4 -4z" fill="#bdc3c7"/>
<path d="M28 0v8h8z" fill="#95a5a6"/>
<text x="50%" y="60%" text-anchor="middle" fill="white" font-size="12" font-family="Arial, sans-serif" font-weight="bold" dy=".3em">EINV</text>
</svg>
</div>
</div>
</div>
<!-- PDF - SO -->
<div class="col-auto">
<div v-if="item.documents.length && item.documents.some(d => d.document_type === 'SALES_ORDER')">
<div v-for="doc in item.documents.filter(d => d.document_type === 'SALES_ORDER')" :key="doc.id">
<div v-for="file in doc.files" v-bind:key="file.id" class="col-auto no-padding">
<document-file-viewer-component :file="file">
<template slot="button">
<div class="bg-grey no-border muted">
<svg width="40" height="48" viewBox="0 0 40 48" xmlns="http://www.w3.org/2000/svg">
<path d="M4 0h24l8 8v40a4 4 0 0 1 -4 4H4a4 4 0 0 1 -4 -4V4a4 4 0 0 1 4 -4z" fill="#27ae60"/>
<path d="M28 0v8h8z" fill="#1e8449"/>
<text x="50%" y="60%" text-anchor="middle" fill="white" font-size="14" font-family="Arial, sans-serif" font-weight="bold" dy=".3em">SO</text>
</svg>
</div>
</template>
</document-file-viewer-component>
</div>
</div>
</div>
<div v-else>
<div class="bg-grey no-border muted">
<svg width="40" height="48" viewBox="0 0 40 48" xmlns="http://www.w3.org/2000/svg">
<path d="M4 0h24l8 8v40a4 4 0 0 1 -4 4H4a4 4 0 0 1 -4 -4V4a4 4 0 0 1 4 -4z" fill="#bdc3c7"/>
<path d="M28 0v8h8z" fill="#95a5a6"/>
<text x="50%" y="60%" text-anchor="middle" fill="white" font-size="14" font-family="Arial, sans-serif" font-weight="bold" dy=".3em">SO</text>
</svg>
</div>
</div>
</div>
<!-- cief todo: 90 - why hide??? -->
<!-- <div class="col-1 hide">
<div class="btn btn-sm all-caps b-rad-none btn-block" :class="{'btn-success': !expanded, 'btn-default': expanded}" @click="expanded = !expanded">
{{ expanded ? 'Cancel' : 'Make Payment' }}</div>
</div> -->
</div>
<div class="row p-t-0 p-b-0 p-l-20 p-r-20">
<div class="col" v-if="storage" v-show="item.type === 16">
<p >Warehouse Storage Fee: {{ storage.numberOfDaysExceeded }} Days x RM {{ storage.pricePerCBM}} x {{ storage.cbm.toFixed(3) }} cbm</p>
</div>
</div>
<div class="row" v-if="$store.getters.isAdmin">
<div class="col">
<div class="row padding-20">
<div class="col"></div>
<div class="col-auto d-flex justify-content-center align-items-center" v-if="$store.getters.isSuperAdmin">
<div class="btn btn-sm btn block all-caps b-rad-none btn-danger pointer requestModal m-l-20" :data-type="'regenerateStorageInvoice-' + item.id" v-if="item.type === 16 && item.status === 3">Regenerate Storage Invoice PDF</div>
<div class="btn btn-sm btn block all-caps b-rad-none btn-danger pointer requestModal m-l-20" :data-type="'regenerateShippingInvoice-' + item.id" v-if="item.type === 1 && !isEinvoiceApplicable">Regenerate Shipping Invoice PDF</div>
<!-- <span class="d-inline-block m-r-15 text-primary bold text-underline pointer requestModal" style="min-width:15px;" v-if="item.type === 16 && item.status !== 3">
<i class="fa fa-ban"></i>
</span> -->
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" :type="'regenerateStorageInvoice-' + item.id" v-if="item.type === 16">
<general-confirmation-form-component
contentText="Are you sure you want to regenerate this Storage Invoice PDF document?"
modalType="delete"
buttonText="Regenerate"
class="text-center"
:apiRoute="route('api.transaction.storage.invoice.regenerate', item.id)"
apiMethod="post"
:section="section"
>
</general-confirmation-form-component>
</modal-component>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" :type="'regenerateShippingInvoice-' + item.id" v-else>
<general-confirmation-form-component
contentText="Are you sure you want to regenerate this Invoice PDF document?"
modalType="delete"
buttonText="Regenerate"
class="text-center"
:apiRoute="route('api.transaction.invoice.regenerate', item.id)"
apiMethod="post"
:section="section"
>
</general-confirmation-form-component>
</modal-component>
<div class="btn btn-sm btn block all-caps b-rad-none btn-danger pointer requestModal m-l-20" :data-type="'regenerateEInvoice-' + item.id" v-if="item.type === 1 && isEinvoiceApplicable">Regenerate E-Invoice PDF</div>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" :type="'regenerateEInvoice-' + item.id">
<general-confirmation-form-component
contentText="Are you sure you want to regenerate this E-Invoice PDF document?"
modalType="delete"
buttonText="Regenerate"
class="text-center"
:apiRoute="route('api.transaction.einvoice.regenerate', item.id)"
apiMethod="post"
:section="section"
>
</general-confirmation-form-component>
</modal-component>
<div class="btn btn-sm btn block all-caps b-rad-none btn-danger pointer requestModal m-l-20" :data-type="'regenerateSalesOrder-' + item.id" v-if="item.type === 1">Regenerate Sales Order PDF</div>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" :type="'regenerateSalesOrder-' + item.id">
<general-confirmation-form-component
contentText="Are you sure you want to regenerate this Sales Order PDF document?"
modalType="delete"
buttonText="Regenerate"
class="text-center"
:apiRoute="route('api.transaction.sales.order.regenerate', item.id)"
apiMethod="post"
:section="section"
>
</general-confirmation-form-component>
</modal-component>
</div>
</div>
</div>
</div>
<div class="row b-t b-grey p-t-10 m-l-5 m-r-5" v-show="expanded" v-if="[5, 6].includes(item.status)">
<div class="col padding-20">
<div class="row bg-master-lightest h-100 padding-20">
<div class="col">
<h6 class="all-caps m-b-5 no-margin text-underline bold">Billing question</h6>
<remark-component :section="section" :data="item" module_type="Transaction"></remark-component>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
data: {
type: Array,
},
invoice_status: {
type: String,
required: true
},
section:{
type: String,
required: true
},
storage:{
type: Object
},
},
data(){
const data = this.data;
const match = data.find(item => item.bill_no.startsWith('SHIP'));
return {
items: data,
parameters: {
packing_list_id: null,
transaction_details: [],
},
expanded: true,
showPaymentProceedModal: false,
showPaymentOutdatedModal: false,
selectedShippingInvoicesOnlyIds: [],
isEinvoiceApplicable: match ? match.is_einvoice_applicable : false,
};
},
watch: {
data: function() {
this.items = this.data;
}
},
computed: {
totalAmount() {
return this.items.reduce((sum, item) => sum + item.amount, 0);
},
totalOutstanding() {
return this.items.reduce((sum, item) => sum + item.outstanding, 0);
},
totalFloating() {
return this.items.reduce((sum, item) => sum + item.floating, 0);
},
selectedIds() {
const ids = [];
this.items.forEach(item => {
ids.push(item.id);
});
return ids;
},
groupPaymentPending(){
if (Array.isArray(this.items)) {
for (let i = 0; i < this.items.length; i++) {
for (let j = 0; j < this.items[i].groups_payment_history.length; j++) {
const item = this.items[i].groups_payment_history[j];
// console.log('item', JSON.stringify(item));
if (item.payment_transaction && item.payment_transaction.status === 1) {
return true;
}
}
}
}
return false;
}
},
methods: {
getLatestComment(item) {
let questions = item.remarks;
return questions.slice().reverse()[0];
},
groupTransactionsExist(items, groups) {
return groups.some(group =>
group.payment_transaction &&
group.transactions_ids.length === items.length &&
group.transactions_ids.every(transaction =>
items.some(item => item.id === transaction.transaction_id)
)
);
},
handleMakePaymentClick(event) {
this.showPaymentProceedModal = false;
this.showPaymentOutdatedModal = false;
this.selectedShippingInvoicesOnlyIds = this.items.filter(invoice => invoice.type === 1).map(s=>s.id);
this.submit(this.route('api.transaction.verify.transactions', JSON.stringify(this.selectedShippingInvoicesOnlyIds)), 'get', 'verifyPaymentForOrderProfileV2Section', false, false);
},
successHandler(response, section){
if(section === "verifyPaymentForOrderProfileV2Section")
{
const totalAmount = response.payload.data.reduce((total, item) => {
const topLevelAmount = item.amount || 0;
const storagesAmount = item.storages ? item.storages.reduce((sum, storage) => {
const storageInvoiceAmount = storage.storageInvoice?.amount || 0;
return sum + storageInvoiceAmount;
}, 0) : 0;
return total + topLevelAmount + storagesAmount;
}, 0);
const epsilon = 0.0001;
if(Math.abs(this.totalOutstanding - totalAmount) < epsilon){
this.showPaymentProceedModal = true;
}
else{
this.showPaymentOutdatedModal = true;
}
}
else{
this.item = response.payload.data;
}
},
paymentOutdated(){
this.showPaymentProceedModal = false;
this.showPaymentOutdatedModal = true;
}
}
}
</script>
+2 -2
View File
@@ -4,8 +4,8 @@ use Illuminate\Support\Facades\Route;
Route::group(['prefix' => 'order', 'as' => 'order.', 'namespace' => 'Orders'], function () {
Route::get('/show/{id}', 'FetchOrderController@fetch')->name('show');
// Route::get('/v2/show/{id}', 'FetchOrderV2Controller@fetch')->name('v2.show');
Route::get('/v2/show/{id}', 'FetchOrderV2Controller@fetch')->middleware('storage.invoice.check.byorder')->name('v2.show');
Route::get('/v2/show/{id}', 'FetchOrderV2Controller@fetch')->name('v2.show');
// Route::get('/v2/show/{id}', 'FetchOrderV2Controller@fetch')->middleware('storage.invoice.check.byorder')->name('v2.show');
Route::get('/list', 'ListOrdersController@list')->name('list');
Route::get('/v2/list', 'ListOrdersV2Controller@list')->name('v2.list');
Route::post('/create', 'CreateOrderController@create')->name('create');
+2
View File
@@ -58,4 +58,6 @@ Route::group(['prefix' => 'transactions', 'namespace' => 'Transactions', 'as' =>
// Route::post('/bulk/po', 'CreateBulkPurchaseOrderDocumentController@create')->name('bulk.po');
});
Route::get('/single/{transaction_id}', 'FetchTransactionController@fetch')->middleware('storage.invoice.check.bytransaction')->name('fetch');
});