diff --git a/app/Classes/General/Eloquent/Filters/OrderByIdDesc.php b/app/Classes/General/Eloquent/Filters/OrderByIdDesc.php
new file mode 100644
index 00000000..547ec9bd
--- /dev/null
+++ b/app/Classes/General/Eloquent/Filters/OrderByIdDesc.php
@@ -0,0 +1,20 @@
+orderBy('id', 'desc');
+ }
+
+}
diff --git a/app/Classes/General/Eloquent/Filters/OrderByUpdatedAtDesc.php b/app/Classes/General/Eloquent/Filters/OrderByUpdatedAtDesc.php
new file mode 100644
index 00000000..7b9c3ead
--- /dev/null
+++ b/app/Classes/General/Eloquent/Filters/OrderByUpdatedAtDesc.php
@@ -0,0 +1,20 @@
+orderBy('updated_at', 'desc');
+ }
+
+}
diff --git a/app/Classes/Modules/Billplzs/ControllersLogic/CallbackBillplzLogic.php b/app/Classes/Modules/Billplzs/ControllersLogic/CallbackBillplzLogic.php
index 75260c9e..2ea66cdc 100644
--- a/app/Classes/Modules/Billplzs/ControllersLogic/CallbackBillplzLogic.php
+++ b/app/Classes/Modules/Billplzs/ControllersLogic/CallbackBillplzLogic.php
@@ -18,6 +18,7 @@ use App\Classes\Modules\Billplzs\Processors\CallbackBillplzProcessor;
use App\Classes\Modules\Transactions\Services\FetchesTransaction;
use App\Classes\Modules\Transactions\Processors\CreatePaymentTransactionProcessor;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
+use App\Classes\Modules\Transactions\Processors\CheckAndCreateStorageInvoiceTransactionProcessor;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Group;
@@ -51,6 +52,9 @@ class CallbackBillplzLogic
/** @var CallbackBillplzProcessor */
private $callbackBillplzProcessor;
+ /** @var CheckAndCreateStorageInvoiceTransactionProcessor */
+ private $storageInvoiceTransactionProcessor;
+
/**
* CallbackBillplzLogic constructor.
* @param GetBillplzBill $getBillplzBill
@@ -60,8 +64,9 @@ class CallbackBillplzLogic
* @param UpdateDoFromYDPortalProcessor $updateDoFromYDPortalProcessor
* @param CreatePaymentTransactionProcessor $createPaymentTransactionProcessor
* @param CallbackBillplzProcessor $callbackBillplzProcessor
+ * @param CheckAndCreateStorageInvoiceTransactionProcessor $storageInvoiceTransactionProcessor
*/
- public function __construct(GetBillplzBill $getBillplzBill, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, UpdateDoFromVTPortalProcessor $updateDoFromVTPortalProcessor, UpdateDoFromYDPortalProcessor $updateDoFromYDPortalProcessor, UpdatesWalletBalance $updatesWalletBalance, CreatePaymentTransactionProcessor $createPaymentTransactionProcessor, CallbackBillplzProcessor $callbackBillplzProcessor)
+ public function __construct(GetBillplzBill $getBillplzBill, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, UpdateDoFromVTPortalProcessor $updateDoFromVTPortalProcessor, UpdateDoFromYDPortalProcessor $updateDoFromYDPortalProcessor, UpdatesWalletBalance $updatesWalletBalance, CreatePaymentTransactionProcessor $createPaymentTransactionProcessor, CallbackBillplzProcessor $callbackBillplzProcessor, CheckAndCreateStorageInvoiceTransactionProcessor $storageInvoiceTransactionProcessor)
{
$this->getBillplzBill = $getBillplzBill;
$this->fetchesTransaction = $fetchesTransaction;
@@ -71,6 +76,7 @@ class CallbackBillplzLogic
$this->updatesWalletBalance = $updatesWalletBalance;
$this->createPaymentTransactionProcessor = $createPaymentTransactionProcessor;
$this->callbackBillplzProcessor = $callbackBillplzProcessor;
+ $this->storageInvoiceTransactionProcessor = $storageInvoiceTransactionProcessor;
}
@@ -115,7 +121,8 @@ class CallbackBillplzLogic
$token = Auth::fromUser(User::find(1));
$request->headers->set('Authorization', 'Bearer '.$token);
- $this->callbackBillplzProcessor->execute($transaction, $status);
+ $this->storageInvoiceBackDoorPreventionCheck($transaction, $status);
+ $result = $this->callbackBillplzProcessor->execute($transaction, $status);
$company_module_marking = $transaction->owner->owner->connections? $transaction->owner->owner->connections->first()->invitee_reference: null;
@@ -126,6 +133,22 @@ class CallbackBillplzLogic
$company_module_marking = $order->companyModule->connections? $order->companyModule->connections->first()->invitee_reference: null;
}
- return $request->method() === 'POST' ? true : view('pages.payments_redirect', ['marking' => $order->reference ?? null, 'company_module_marking' => $company_module_marking ?? null, 'transaction' => $transaction, 'status' => $status]);
+ return $request->method() === 'POST' ? true : view('pages.payments_redirect', ['marking' => $order->reference ?? null, 'company_module_marking' => $company_module_marking ?? null, 'transaction' => $transaction, 'status' => $status, 'result' => $result]);
+ }
+
+ private function storageInvoiceBackDoorPreventionCheck($transaction, $status){
+ if ($transaction->owner instanceof Wallet && $status === ApprovalStatus::APPROVED) {
+ $group = Group::where('reference', $transaction->payment_reference)->first();
+ if ($group) {
+ foreach ($group->groupTransactions as $groupTransaction) {
+ $invoice = $groupTransaction->transaction;
+ $pL = $invoice->owner;
+ $order = $pL->owner;
+ if($order){
+ $this->storageInvoiceTransactionProcessor->executeOrder($order, false); //original was set true here so that no group is soft deleted or billplz bill got deleted
+ }
+ }
+ }
+ }
}
}
diff --git a/app/Classes/Modules/Billplzs/Processors/CallbackBillplzProcessor.php b/app/Classes/Modules/Billplzs/Processors/CallbackBillplzProcessor.php
index 5bd9c0c0..83ce7d82 100644
--- a/app/Classes/Modules/Billplzs/Processors/CallbackBillplzProcessor.php
+++ b/app/Classes/Modules/Billplzs/Processors/CallbackBillplzProcessor.php
@@ -65,6 +65,9 @@ class CallbackBillplzProcessor
$invoice = $transaction->owner;
$packingList = $invoice->owner;
+ $proceed = $this->checkAmountPaidVSRequired($transaction);
+ if(!$proceed) return false;
+
$this->updatesTransactionStatus->execute($transaction, $status);
// check if is wallet top up
@@ -95,13 +98,39 @@ class CallbackBillplzProcessor
if (!$transaction->owner instanceof Wallet) {
$this->processPackingListAndInvoice($packingList, $invoice);
}
+
+ return true;
+ }
+
+ private function checkAmountPaidVSRequired($transaction){
+ //command:check-storage-invoices must already run for this part of the code to work properly
+ $group = Group::withTrashed()->where('reference', $transaction->payment_reference)->first();
+ if ($group) {
+ $totalAmountToBePaid = 0;
+ $actualAmountPaid = $transaction->amount;
+
+ foreach ($group->groupTransactions as $groupTransaction) {
+ $invoice = $groupTransaction->transaction;
+ $totalAmountToBePaid += $invoice->amount;
+ }
+
+ if(($totalAmountToBePaid - $actualAmountPaid) < 0.01){
+
+ }
+ else{
+ Log::channel('storage_invoices')->info('Total amount from current transaction: '.$totalAmountToBePaid); //cief todo: to be removed
+ Log::channel('storage_invoices')->info('Total amount from paid transaction: '.$transaction->amount); //cief todo: to be removed
+ return false;
+ }
+ }
+ return true;
}
private function processPackingListAndInvoice($packingList, $invoice = null){
$result = false;
$totalInvoicesAmountPaid = 0.00;
$totalInvoicesAmount = 0.00;
- $invoiceTransactions = $packingList->transactions()->whereIn('type', [TransactionType::SHIPPING_INVOICE, TransactionType::STORAGE_INVOICE])->get();
+ $invoiceTransactions = $packingList->transactions()->where('status', [ApprovalStatus::APPROVED])->whereIn('type', [TransactionType::SHIPPING_INVOICE, TransactionType::STORAGE_INVOICE])->get();
//Part 1: Process each single invoice type and get the total of all invoices
foreach($invoiceTransactions as $invoiceTransaction){
@@ -121,12 +150,12 @@ class CallbackBillplzProcessor
$totalInvoicesAmountPaid = $totalInvoicesAmountPaid + $totalInvoiceAmountPaid;
}
- Log::info('Total invoice amount paid 1: '.$totalInvoicesAmount); //cief todo: to be removed
- Log::info('Total invoice amount paid 2: '.$totalInvoicesAmountPaid); //cief todo: to be removed
+ Log::channel('storage_invoices')->info('Total invoice amount paid 1: '.$totalInvoicesAmount); //cief todo: to be removed
+ Log::channel('storage_invoices')->info('Total invoice amount paid 2: '.$totalInvoicesAmountPaid); //cief todo: to be removed
//Part 2: Based on the collected info for all the total of all invoices
if (($totalInvoicesAmount - $totalInvoicesAmountPaid) < 0.01) {
- Log::info('Total invoice amount paid 3: '.$totalInvoicesAmountPaid); //cief todo: to be removed
+ Log::channel('storage_invoices')->info('Total invoice amount paid 3: '.$totalInvoicesAmountPaid); //cief todo: to be removed
$packingList->status = ApprovalStatus::APPROVED;
$packingList->save();
diff --git a/app/Classes/Modules/Billplzs/Services/DeletesBillplzBill.php b/app/Classes/Modules/Billplzs/Services/DeletesBillplzBill.php
new file mode 100644
index 00000000..afceedb7
--- /dev/null
+++ b/app/Classes/Modules/Billplzs/Services/DeletesBillplzBill.php
@@ -0,0 +1,34 @@
+delete(config('billplz.base_url').'/api/v3/bills/'.$billID);
+ Log::channel('storage_invoices')->info('DeletesBillplzBill response: '.json_encode($response));
+
+ if($response->successful()){
+ $data = $response->json();
+
+ // $data['url'] = $data['url'].'?auto_submit=true';
+
+ return (object) $data;
+ }else{
+ return null;
+ }
+ }catch(\Exception $exception){
+ throw new MalformedRequestException('Unable to get correct response from billplz server: ' . $exception->getMessage());
+ }
+ }
+}
diff --git a/app/Classes/Modules/Orders/ControllersLogic/FetchOrderV2Logic.php b/app/Classes/Modules/Orders/ControllersLogic/FetchOrderV2Logic.php
index d3dc6005..9966d18c 100644
--- a/app/Classes/Modules/Orders/ControllersLogic/FetchOrderV2Logic.php
+++ b/app/Classes/Modules/Orders/ControllersLogic/FetchOrderV2Logic.php
@@ -52,8 +52,10 @@ class FetchOrderV2Logic extends AbstractControllerLogic
$this->canFetchOrder->passes();
$query = $this->fetchesOrder->execute(['reference' => $request->route('id'), 'with_packing_lists' => true]);
- $query->storages = $request->input('storages'); //from middleware
+ if($request->input('storages')){
+ $query->storages = $request->input('storages'); //from middleware
+ }
return $this->resourceResponse(new OrderV2Resource($query));
diff --git a/app/Classes/Modules/PackingLists/Processors/FetchContainersFromYdPortalProcessor.php b/app/Classes/Modules/PackingLists/Processors/FetchContainersFromYdPortalProcessor.php
index 6056f06b..878253b4 100644
--- a/app/Classes/Modules/PackingLists/Processors/FetchContainersFromYdPortalProcessor.php
+++ b/app/Classes/Modules/PackingLists/Processors/FetchContainersFromYdPortalProcessor.php
@@ -121,7 +121,7 @@ class FetchContainersFromYdPortalProcessor
$containerReference = explode('预计到港时间', $tracking[1])[0];
$loadingDate = Carbon::parse($trackingRow->trackingtime);
$etd = Carbon::parse($tracking[2])->subDays(5);
- $eta = Carbon::parse($tracking[2])->addDays(2);
+ // $eta = Carbon::parse($tracking[2])->addDays(2); //omair to review
}
}
diff --git a/app/Classes/Modules/PackingLists/Processors/FetchContainersUpdatesFromYdPortalProcessor.php b/app/Classes/Modules/PackingLists/Processors/FetchContainersUpdatesFromYdPortalProcessor.php
index 3b0e1679..9222864a 100644
--- a/app/Classes/Modules/PackingLists/Processors/FetchContainersUpdatesFromYdPortalProcessor.php
+++ b/app/Classes/Modules/PackingLists/Processors/FetchContainersUpdatesFromYdPortalProcessor.php
@@ -147,7 +147,7 @@ class FetchContainersUpdatesFromYdPortalProcessor
if($delayDate){
- $delayDate = $delayDate->addDays(2);
+ // $delayDate = $delayDate->addDays(2); //omair to review
$transport = $container->transports()->first();
if(!$transport->schedules()->whereDate('eta', '>=', $delayDate)->first()) {
diff --git a/app/Classes/Modules/Transactions/ControllersLogic/ListTransactionsLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/ListTransactionsLogic.php
index 15cb9bfc..c0a77b50 100644
--- a/app/Classes/Modules/Transactions/ControllersLogic/ListTransactionsLogic.php
+++ b/app/Classes/Modules/Transactions/ControllersLogic/ListTransactionsLogic.php
@@ -5,10 +5,11 @@ namespace App\Classes\Modules\Transactions\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Transactions\Services\ListsTransactions;
-use App\Http\Resources\BookingResource;
use App\Http\Resources\TransactionResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Log;
+
class ListTransactionsLogic extends AbstractControllerLogic
{
@@ -38,13 +39,18 @@ class ListTransactionsLogic extends AbstractControllerLogic
public function logic(Request $request) : JsonResponse
{
-
$query = $this->listsTransactions->execute($this->listsTransactions->deserializeFilters($request->input('filters')));
+ if($request->input('storages')){
+ foreach ($query->items() as &$item) {
+ $transactionId = $item['id'];
+ $filteredStorages = array_filter($request->input('storages'), function ($storage) use ($transactionId) {
+ return isset($storage['parentInvoiceId']) && $storage['parentInvoiceId'] == $transactionId;
+ });
+ $item['storages'] = $filteredStorages;
+ }
+ }
+
return $this->collectionResponse(TransactionResource::collection($query));
-
}
-
-
-
}
diff --git a/app/Classes/Modules/Transactions/Processors/CheckAndCreateStorageInvoiceTransactionProcessor.php b/app/Classes/Modules/Transactions/Processors/CheckAndCreateStorageInvoiceTransactionProcessor.php
index 0b28b6b2..8d9493fa 100644
--- a/app/Classes/Modules/Transactions/Processors/CheckAndCreateStorageInvoiceTransactionProcessor.php
+++ b/app/Classes/Modules/Transactions/Processors/CheckAndCreateStorageInvoiceTransactionProcessor.php
@@ -13,6 +13,7 @@ use App\Classes\Modules\Transactions\Services\FetchesTransaction;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionDetail;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
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;
@@ -22,7 +23,8 @@ use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\PackageType;
use App\Classes\ValueObjects\Constants\TransactionDetailType;
-
+use App\Http\Resources\TransactionResource;
+use App\Models\Order;
use App\Models\PackingList;
use App\Models\Transaction;
use Carbon\Carbon;
@@ -58,6 +60,9 @@ class CheckAndCreateStorageInvoiceTransactionProcessor
/** @var DeletesGroup */
private $deletesGroup;
+ /** @var DeletesBillplzBill */
+ private $deletesBillplzBill;
+
/**
* @param FetchesOrder $fetchesOrder
* @param GeneratesTransactionBillNumber $generatesTransactionBillNumber
@@ -68,8 +73,9 @@ class CheckAndCreateStorageInvoiceTransactionProcessor
* @param UpdatesTransactionDetail $updatesTransactionDetail
* @param UpdatesTransactionStatus $updatesTransactionStatus
* @param DeletesGroup $deletesGroup
+ * @param DeletesBillplzBill $deletesBillplzBill
*/
- public function __construct(FetchesOrder $fetchesOrder, GeneratesTransactionBillNumber $generatesTransactionBillNumber, FetchesTransaction $fetchesTransaction, CreatesTransaction $createsTransaction, CreatesTransactionDetail $createsTransactionDetail, UpdatesTransaction $updatesTransaction, UpdatesTransactionDetail $updatesTransactionDetail, UpdatesTransactionStatus $updatesTransactionStatus, DeletesGroup $deletesGroup)
+ public function __construct(FetchesOrder $fetchesOrder, GeneratesTransactionBillNumber $generatesTransactionBillNumber, FetchesTransaction $fetchesTransaction, CreatesTransaction $createsTransaction, CreatesTransactionDetail $createsTransactionDetail, UpdatesTransaction $updatesTransaction, UpdatesTransactionDetail $updatesTransactionDetail, UpdatesTransactionStatus $updatesTransactionStatus, DeletesGroup $deletesGroup, DeletesBillplzBill $deletesBillplzBill)
{
$this->fetchesOrder = $fetchesOrder;
$this->generatesTransactionBillNumber = $generatesTransactionBillNumber;
@@ -80,50 +86,72 @@ class CheckAndCreateStorageInvoiceTransactionProcessor
$this->updatesTransactionDetail = $updatesTransactionDetail;
$this->updatesTransactionStatus = $updatesTransactionStatus;
$this->deletesGroup = $deletesGroup;
+ $this->deletesBillplzBill = $deletesBillplzBill;
}
/**
* @throws MalformedRequestException
*/
- public function execute(int $orderId)
+ public function execute(int $orderReference)
{
- $multipleResults = array();
- $order = $this->fetchesOrder->execute(['reference' => $orderId, 'with_packing_lists' => true]);
+ $order = $this->fetchesOrder->execute(['reference' => $orderReference, 'with_packing_lists' => true]);
+ return $this->executeOrder($order);
+ }
- $eta = "";
- $destinationWarehousePackages = $order->destinationWarehousePackages;
- foreach ($destinationWarehousePackages as $destinationWarehousePackage){
- if ($destinationWarehousePackage) {
- $package = $destinationWarehousePackage->packages->first();
- if ($package) {
- $container = $package->container()->first();
- if ($container) {
- $transport = $container->transports->first();
- if ($transport) {
- $schedule = $transport->schedules->last();
- if ($schedule) {
- $eta = $schedule->eta;
+ public function executeOrder(Order $order, bool $isBackDoorCheck = false){
+ $results = [];
+ $marking = $order->companyModule->inviters()->withPivot('invitee_reference')->first()->pivot->invitee_reference;
+ $is_credit_term = $order->companyModule->inviters()->withPivot('is_credit_term')->first()->pivot->is_credit_term;
+ if(!$is_credit_term){
+ Log::channel('storage_invoices')->info('orderId: '.$order->id.', orderReference: '.$order->reference.', marking: '.$marking.', is_credit_term: '.$is_credit_term);
+ $packingLists = $order->destinationWarehousePackages;
+ foreach ($packingLists as $packingList){
+ Log::channel('storage_invoices')->info('destinationWarehousePackage: '.json_encode($packingList));
+ $eta = $this->getEtaFromPackingList($packingList);
+ if($eta){
+ $transactions = $packingList->transactions()->where('transactions.type', TransactionType::SHIPPING_INVOICE)->whereIn('transactions.status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->get();
+ // $transactions = $destinationWarehousePackage->transactions()->where('transactions.type', TransactionType::SHIPPING_INVOICE)->where('transactions.status', ApprovalStatus::APPROVED)->get();
- if($eta){
- $transactions = $destinationWarehousePackage->transactions()->where('transactions.type', TransactionType::SHIPPING_INVOICE)->whereIn('transactions.status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->get();
- // $transactions = $destinationWarehousePackage->transactions()->where('transactions.type', TransactionType::SHIPPING_INVOICE)->where('transactions.status', ApprovalStatus::APPROVED)->get();
-
- /** @var Transaction $invoice_transaction */
- foreach ($transactions as $invoice_transaction){
- $multipleResults[] = $this->processSingleTransactionOfTypeShippingInvoice($invoice_transaction, $destinationWarehousePackage, $order, $eta);
- }
- }
- }
+ /** @var Transaction $invoice_transaction */
+ foreach ($transactions as $invoice_transaction){
+ $result = $this->processSingleTransactionOfTypeShippingInvoice($invoice_transaction, $packingList, $order->company_module_id, $eta, $isBackDoorCheck);
+ if($result){
+ $results[] = $result;
}
}
}
}
}
-
- return $multipleResults;
+ return $results;
}
- function processSingleTransactionOfTypeShippingInvoice($transaction, $destinationWarehousePackage, $order, $eta){
+ private function getEtaFromPackingList($packingList){
+ if ($packingList) {
+ $package = $packingList->packages->first();
+ if ($package) {
+ $container = $package->container()->first();
+ if ($container) {
+ $transport = $container->transports->first();
+ if ($transport) {
+ // $container->transports()->first()->update(['drop_date' => $unstuffingDate, 'status' => ApprovalStatus::COMPLETED]);
+ // $arrivalDateAtChinaWarehouse = Carbon::parse($transport->drop_date); //cief todo: to uncomment this
+ $arrivalDateAtChinaWarehouse = Carbon::parse('2021-11-13 00:00:00');
+ $dateToCompare = Carbon::parse('2023-11-13 00:00:00');
+ if ($dateToCompare->isAfter($arrivalDateAtChinaWarehouse)) {
+ Log::channel('storage_invoices')->info('dateToCompare: '.$dateToCompare.', arrivalDateAtChinaWarehouse: '.$arrivalDateAtChinaWarehouse);
+ $schedule = $transport->schedules->last();
+ if ($schedule) {
+ return $schedule->eta;
+ }
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ private function processSingleTransactionOfTypeShippingInvoice($transaction, $destinationWarehousePackage, $company_module_id, $eta, $isBackDoorCheck){
$pricePerCBM = 3;
$resultNumberOfDaysFree = 10;
$dt1 = $eta->copy()->addDay()->startOfDay();
@@ -131,7 +159,16 @@ class CheckAndCreateStorageInvoiceTransactionProcessor
$currentDatetime = Carbon::now();
$dt2 = $currentDatetime->copy()->addDay()->startOfDay();
$resultCurrentDate = $dt2->format('Y-m-d H:i:s');
+ $test = Carbon::parse($dt2);
$interval = Carbon::parse($dt2)->diff($dt1);
+ $interval2 = $dt2->diff($dt1);
+
+ //cief todo: to be deleted
+ // Log::channel('storage_invoices')->info('currentDatetime: '.$currentDatetime);
+ // Log::channel('storage_invoices')->info('dt1: '.$dt1.', resultStartDate: '.$resultStartDate);
+ // Log::channel('storage_invoices')->info('dt2: '.$dt2.', resultCurrentDate: '.$resultCurrentDate);
+ // Log::channel('storage_invoices')->info('interval: '.$interval->days.', test: '.$test.', interval2: '.$interval2->days);
+
$resultNumberOfDaysExceeded = $interval->days - $resultNumberOfDaysFree;
$storageInvoice = $destinationWarehousePackage->transactions()->where('transactions.type', TransactionType::STORAGE_INVOICE)->first();
@@ -150,67 +187,85 @@ class CheckAndCreateStorageInvoiceTransactionProcessor
if(!$storageInvoice && $resultNumberOfDaysExceeded > 0 && $transaction->status != ApprovalStatus::COMPLETED){
$billNumber = $this->generatesTransactionBillNumber->execute('STOR-');
- $invoiceTransaction = $this->createTransaction($destinationWarehousePackage, $billNumber, $order->company_module_id, $price_cbm);
- $storageInvoiceId = $invoiceTransaction->id;
- $this->createTransactionDetails($invoiceTransaction, $destinationWarehousePackage, $cbm, 3 * $resultNumberOfDaysExceeded, $resultNumberOfDaysExceeded);
+ $storageInvoice = $this->createStorageInvoiceTransaction($destinationWarehousePackage, $billNumber, $company_module_id, $price_cbm);
+ $storageInvoiceId = $storageInvoice->id;
+ $this->createStorageInvoiceTransactionDetails($storageInvoice, $destinationWarehousePackage, $cbm, 3 * $resultNumberOfDaysExceeded, $resultNumberOfDaysExceeded);
}
else if($storageInvoice){
$amount = $storageInvoice->amount;
$epsilon = 0.0001; // Tolerance for the comparison
-
- //cief todo: to be removed - starts
- Log::info('price_cbm: '.$price_cbm."-".gettype($price_cbm));
- Log::info('amount: '.$amount."-".gettype($amount));
- if (abs($price_cbm - $amount) > $epsilon) {
- Log::info("The values are not equal.");
- } else {
- Log::info("The values are approximately equal.");
- }
- //cief todo: to be removed - ends
+ Log::channel('storage_invoices')->info('$transaction->id,: '.$transaction->id);
+ Log::channel('storage_invoices')->info('$storageInvoice->status,: '.$storageInvoice->status);
+ Log::channel('storage_invoices')->info('price_cbm: '.$price_cbm."-".gettype($price_cbm));
if(abs($price_cbm - $amount) > $epsilon && $storageInvoice->status !== ApprovalStatus::COMPLETED){
$paymentTransactions = $storageInvoice->transactions()->where('transactions.type', TransactionType::PAYMENT)->where('transactions.status', ApprovalStatus::PENDING_SUBMISSION)->get();
- if(count($paymentTransactions) > 0){ //PAYMENT type
- foreach ($paymentTransactions as $paymentTransaction){
- $this->updatesTransactionStatus->execute($paymentTransaction, ApprovalStatus::EXPIRED);
+
+ if(!$isBackDoorCheck){
+ if(count($paymentTransactions) > 0){
+ $this->updatePaymentTransactionViaNonGroupPayment($paymentTransactions);
}
- }
- else{ //TOP UP type
- $groups = $storageInvoice->groups()->get();
- foreach ($groups as $grp){
- $groupReference = $grp->reference;
- $walletTransaction = $this->fetchesTransaction->execute(['payment_reference' => $groupReference]);
- if($walletTransaction->status === ApprovalStatus::PENDING_SUBMISSION || $walletTransaction->status === ApprovalStatus::PENDING_VERIFICATION){
- $grp->status = ApprovalStatus::EXPIRED;
- $grp->save();
- $this->deletesGroup->execute($grp);
- $this->updatesTransactionStatus->execute($walletTransaction, ApprovalStatus::EXPIRED);
- }
+ else{
+ $this->updatePaymentTransactionViaGroupPayment($storageInvoice);
}
}
- $invoiceTransaction = $this->updateTransaction($storageInvoice, $price_cbm);
+ $storageInvoice = $this->updateStorageInvoiceTransaction($storageInvoice, $price_cbm);
$invoiceTransactionDetails = $storageInvoice->transactionDetails()->first();
- $this->updateTransactionDetails($invoiceTransactionDetails, $cbm, 3 * $resultNumberOfDaysExceeded);
+ $this->updateStorageInvoiceTransactionDetails($invoiceTransactionDetails, $cbm, 3 * $resultNumberOfDaysExceeded);
}
+
$storageInvoiceId = $storageInvoice->id;
}
- $result = [
- 'parentInvoiceId' => $transaction->id,
- 'storageInvoiceId' => $storageInvoiceId,
- 'numberOfDaysExceeded' => $resultNumberOfDaysExceeded,
- 'numberOfDaysFree' => $resultNumberOfDaysFree,
- 'startDate' => $resultStartDate,
- 'currentDate' => $resultCurrentDate,
- 'cbm' => $cbm,
- 'pricePerCBM' => $pricePerCBM,
- ];
+ if($storageInvoiceId !== 0){
+ $result = [
+ 'parentInvoiceId' => $transaction->id,
+ 'storageInvoiceId' => $storageInvoiceId,
+ 'numberOfDaysExceeded' => $resultNumberOfDaysExceeded,
+ 'numberOfDaysFree' => $resultNumberOfDaysFree,
+ 'startDate' => $resultStartDate,
+ 'currentDate' => $resultCurrentDate,
+ 'cbm' => $cbm,
+ 'pricePerCBM' => $pricePerCBM,
+ 'storageInvoice' => new TransactionResource($storageInvoice)
+ ];
+ return $result;
+ }
- return $result;
}
- function updateTransaction(Transaction $transaction, float $totalAmount){
+ private function updatePaymentTransactionViaGroupPayment($storageInvoice){
+ Log::channel('storage_invoices')->info('updatePaymentTransactionViaGroupPayment');
+ $groups = $storageInvoice->groups()->get();
+ foreach ($groups as $grp){
+ $groupReference = $grp->reference;
+ $walletTransaction = $this->fetchesTransaction->execute(['payment_reference' => $groupReference]);
+ if($walletTransaction->status === ApprovalStatus::PENDING_SUBMISSION || $walletTransaction->status === ApprovalStatus::PENDING_VERIFICATION){
+ $grp->status = ApprovalStatus::EXPIRED;
+ $grp->save();
+ $this->deletesGroup->execute($grp);
+ $this->updatesTransactionStatus->execute($walletTransaction, ApprovalStatus::EXPIRED);
+ if($walletTransaction->payment_reference){
+ $deletedBillplzBill = $this->deletesBillplzBill->execute($walletTransaction->payment_reference);
+ Log::channel('storage_invoices')->info('deletedBillplzBill TransactionType::WALLET: '.json_encode($deletedBillplzBill));
+ }
+ }
+ }
+ }
+
+ private function updatePaymentTransactionViaNonGroupPayment($paymentTransactions){
+ Log::channel('storage_invoices')->info('updatePaymentTransactionViaNonGroupPayment');
+ foreach ($paymentTransactions as $paymentTransaction){
+ $this->updatesTransactionStatus->execute($paymentTransaction, ApprovalStatus::EXPIRED);
+ if($paymentTransaction->payment_reference){
+ $deletedBillplzBill = $this->deletesBillplzBill->execute($paymentTransaction->payment_reference);
+ Log::channel('storage_invoices')->info('deletedBillplzBill TransactionType::WALLET: '.json_encode($deletedBillplzBill));
+ }
+ }
+ }
+
+ private function updateStorageInvoiceTransaction(Transaction $transaction, float $totalAmount){
$object = new TransactionObject(
$transaction->bill_no,
@@ -236,7 +291,7 @@ class CheckAndCreateStorageInvoiceTransactionProcessor
return $invoice_transaction;
}
- function updateTransactionDetails($invoice_transaction_details, $cbm, $price_cbm){
+ private function updateStorageInvoiceTransactionDetails($invoice_transaction_details, $cbm, $price_cbm){
$object_detail = new TransactionDetailObject(
'STORAGE_FEE',
$invoice_transaction_details->name,
@@ -247,7 +302,7 @@ class CheckAndCreateStorageInvoiceTransactionProcessor
$this->updatesTransactionDetail->execute($invoice_transaction_details, $object_detail);
}
- function createTransaction(PackingList $packing_list, string $billNumber, int $companyModuleId, float $totalAmount){
+ private function createStorageInvoiceTransaction(PackingList $packing_list, string $billNumber, int $companyModuleId, float $totalAmount){
$object = new TransactionObject(
$billNumber,
@@ -273,7 +328,7 @@ class CheckAndCreateStorageInvoiceTransactionProcessor
return $invoice_transaction;
}
- function createTransactionDetails($invoice_transaction, PackingList $packing_list, $cbm, $price_cbm, $numberOfDays){
+ private function createStorageInvoiceTransactionDetails($invoice_transaction, PackingList $packing_list, $cbm, $price_cbm, $numberOfDays){
$object_detail = new TransactionDetailObject(
'SHIPPING_FEE',
TransactionDetailType::STORAGE_FEE.' for '.$numberOfDays. ' days
'.round($packing_list->packages->where('type', '!=', PackageType::OVER_WEIGHT)->sum('quantity'), 3).' CTNS - '.round($cbm, 3).' CBM',
diff --git a/app/Console/Commands/CheckStorageInvoices.php b/app/Console/Commands/CheckStorageInvoices.php
new file mode 100644
index 00000000..5644a84f
--- /dev/null
+++ b/app/Console/Commands/CheckStorageInvoices.php
@@ -0,0 +1,85 @@
+listsGroups = $listsGroups;
+ $this->storageInvoiceTransactionProcessor = $storageInvoiceTransactionProcessor;
+ }
+
+
+ /**
+ * Execute the console command.
+ *
+ * @return int
+ */
+ public function handle()
+ {
+ ini_set('memory_limit', '-1');
+
+ $this->info(Carbon::now() . ': Start Check all pending group payment with storage invoice is valid.');
+ $start = new Carbon();
+
+
+ $newfilters['order_by_updated_at_desc'] = true;
+ $newfilters['status_in'] = [0, 1];
+ $groups = $this->listsGroups->execute($newfilters);
+
+ foreach ($groups as $group){
+ $this->info('CheckForStorageInvoiceByTransactions group: '.json_encode($group));
+ foreach ($group->groupTransactions as $groupTransaction) {
+ $invoice = $groupTransaction->transaction;
+ $packingList = $invoice->owner()->first();
+ if($packingList){
+ $order = $packingList->owner()->first();
+ if($order instanceof Order){
+ $storages = $this->storageInvoiceTransactionProcessor->executeOrder($order);
+ }
+ }
+ }
+ }
+
+
+ $end = new Carbon();
+ $elapsedTime = $start->diff($end)->format('%H:%I:%S');
+
+ $this->info(Carbon::now() . ': Done Check all pending group payment with storage invoice is valid. ElapsedTime: ' . $elapsedTime . '.');
+ }
+}
diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php
index be5caaa9..4d355110 100644
--- a/app/Console/Kernel.php
+++ b/app/Console/Kernel.php
@@ -62,6 +62,11 @@ class Kernel extends ConsoleKernel
->hourly()
->withoutOverlapping()
->appendOutputTo (storage_path().'/logs/fix_failed_callback_from_billplz.log');
+
+ $schedule->command('command:check-storage-invoices')
+ ->dailyAt('0:01')
+ ->withoutOverlapping()
+ ->appendOutputTo(storage_path().'/logs/check_storage_invoices.log');
}
/**
diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php
index 7ef04da8..d458f7b1 100644
--- a/app/Http/Kernel.php
+++ b/app/Http/Kernel.php
@@ -72,5 +72,6 @@ class Kernel extends HttpKernel
'token.check' => \App\Http\Middleware\TokenCheckerMiddleware::class,
'storage.invoice.check.byorder' => \App\Http\Middleware\CheckForStorageInvoiceByOrderId::class,
'storage.invoice.check.bytransactions' => \App\Http\Middleware\CheckForStorageInvoiceByTransactions::class,
+ 'storage.invoice.check.bygroup' => \App\Http\Middleware\CheckForStorageInvoiceByGroup::class,
];
}
diff --git a/app/Http/Middleware/CheckForStorageInvoiceByGroup.php b/app/Http/Middleware/CheckForStorageInvoiceByGroup.php
new file mode 100644
index 00000000..b80ceeaa
--- /dev/null
+++ b/app/Http/Middleware/CheckForStorageInvoiceByGroup.php
@@ -0,0 +1,64 @@
+storageInvoiceTransactionProcessor = $storageInvoiceTransactionProcessor;
+ $this->listsGroups = $listsGroups;
+ }
+
+
+ /**
+ * 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)
+ {
+ // :options="{'per_page': 10, order_by: {column: 'id', DESC: true}, 'status_in': [0, 1], 'receiver': company_module_id, order_by: {column: 'updated_at', DESC: true}}"
+ $filters = json_decode($request->input('filters'), true);
+ if(json_encode($filters['order_by']) == '{"column":"updated_at","DESC":true}'){
+ $filters['order_by_updated_at_desc'] = true;
+ }
+ unset($filters['order_by']);
+ $groups = $this->listsGroups->execute($filters);
+
+
+ if(isset($filters['check_for_storage_invoice'])){
+ foreach ($groups as $group){
+ foreach ($group->groupTransactions as $groupTransaction) {
+ $invoice = $groupTransaction->transaction;
+ $packingList = $invoice->owner()->first();
+ if($packingList){
+ $order = $packingList->owner()->first();
+ if($order instanceof Order){
+ $storages = $this->storageInvoiceTransactionProcessor->executeOrder($order);
+ }
+ }
+ }
+ }
+ }
+
+ return $next($request);
+ }
+}
diff --git a/app/Http/Middleware/CheckForStorageInvoiceByOrderId.php b/app/Http/Middleware/CheckForStorageInvoiceByOrderId.php
index 8e1f4efc..8256241c 100644
--- a/app/Http/Middleware/CheckForStorageInvoiceByOrderId.php
+++ b/app/Http/Middleware/CheckForStorageInvoiceByOrderId.php
@@ -29,9 +29,8 @@ class CheckForStorageInvoiceByOrderId
public function handle(Request $request, Closure $next)
{
$orderId = $request->route('id');
- $result = $this->storageInvoiceTransactionProcessor->execute($orderId);
- $request->merge(['storages' => $result]);
-
+ $storages = $this->storageInvoiceTransactionProcessor->execute($orderId);
+ $request->merge(['storages' => $storages]);
return $next($request);
}
}
diff --git a/app/Http/Middleware/CheckForStorageInvoiceByTransactions.php b/app/Http/Middleware/CheckForStorageInvoiceByTransactions.php
index 443030dd..ab68fe5f 100644
--- a/app/Http/Middleware/CheckForStorageInvoiceByTransactions.php
+++ b/app/Http/Middleware/CheckForStorageInvoiceByTransactions.php
@@ -5,10 +5,12 @@ namespace App\Http\Middleware;
use Closure;
use App\Classes\Modules\Transactions\Processors\CheckAndCreateStorageInvoiceTransactionProcessor;
use App\Classes\Modules\Transactions\Services\ListsTransactions;
+use App\Classes\Modules\Transactions\Services\ListsGroups;
+use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\CompanyConnection;
use App\Models\Order;
-use App\Models\PackingList;
use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Log;
class CheckForStorageInvoiceByTransactions
{
@@ -19,11 +21,15 @@ class CheckForStorageInvoiceByTransactions
/** @var ListsTransactions */
private $listsTransactions;
+ /** @var ListsGroups */
+ private $listsGroups;
- public function __construct(CheckAndCreateStorageInvoiceTransactionProcessor $storageInvoiceTransactionProcessor, ListsTransactions $listsTransactions)
+
+ public function __construct(CheckAndCreateStorageInvoiceTransactionProcessor $storageInvoiceTransactionProcessor, ListsTransactions $listsTransactions, ListsGroups $listsGroups)
{
$this->storageInvoiceTransactionProcessor = $storageInvoiceTransactionProcessor;
$this->listsTransactions = $listsTransactions;
+ $this->listsGroups = $listsGroups;
}
@@ -36,37 +42,56 @@ class CheckForStorageInvoiceByTransactions
*/
public function handle(Request $request, Closure $next)
{
- //{"per_page":999,"order_by":{"column":"id","DESC":true},"status_in":[2],"receiver":298,"type_in":[1,16],"does_not_have_payment_status_in":[0,1],"does_not_have_groups":1}
+ $results = [];
$transactions = null;
$marking = $request->route('marking');
- if($marking){
+ if($marking){ //for web route /customer/{marking}/payment-and-billing
$connection = CompanyConnection::where('invitee_reference', $marking)->first();
$company_module_id = $connection->invitee->id;
$filters = [
'per_page' => 999,
'status_in' => [2],
'receiver' => $company_module_id,
- 'type_in' => [1, 16]
+ 'type_in' => [TransactionType::SHIPPING_INVOICE]
];
$transactions = $this->listsTransactions->execute($filters);
}
- else{
+ else{ //for api route /transactions/list
$filters = json_decode($request->input('filters'), true);
- $filters['per_page'] = 999;
- unset($filters['does_not_have_payment_status_in']);
- unset($filters['does_not_have_groups']);
+ $filters['type_in'] = [TransactionType::SHIPPING_INVOICE];
+ if(json_encode($filters['order_by']) == '{"column":"id","DESC":true}'){
+ Log::channel('storage_invoices')->info('CheckForStorageInvoiceByTransactions 3 Match');
+ $filters['order_by_id_desc'] = true;
+ }
unset($filters['order_by']);
$transactions = $this->listsTransactions->execute($filters);
}
- foreach($transactions as $transaction){
- $packingList = $transaction->owner()->first();
- $order = $packingList->owner()->first();
- if($order instanceof Order){
- $this->storageInvoiceTransactionProcessor->execute($order->reference);
+
+ if(isset($filters['check_for_storage_invoice'])){
+ foreach($transactions as $transaction){
+ $packingList = $transaction->owner()->first();
+ if($packingList){
+ $order = $packingList->owner()->first();
+ if($order instanceof Order){
+ $storages = $this->storageInvoiceTransactionProcessor->executeOrder($order);
+ if($storages){
+ $results = array_merge($results, $storages);
+ }
+ }
+ }
}
}
+ $filteredResults = array_values(array_filter($results, function($item, $key) {
+ static $seen = array();
+ $hash = md5($item['parentInvoiceId'] . $item['storageInvoiceId']);
+ return !isset($seen[$hash]) && ($seen[$hash] = true);
+ }, ARRAY_FILTER_USE_BOTH));
+
+
+ $request->merge(['storages' => $filteredResults]);
+
return $next($request);
}
}
diff --git a/app/Http/Resources/GroupForOrderV2Resource.php b/app/Http/Resources/GroupForOrderV2Resource.php
new file mode 100644
index 00000000..d5cf69e8
--- /dev/null
+++ b/app/Http/Resources/GroupForOrderV2Resource.php
@@ -0,0 +1,39 @@
+ $this->id,
+ 'original_amount' => (float) $this->original_amount,
+ 'original_currency' => new CurrencyResource($this->original_currency),
+ 'issuer_name' => $this->issuerCompany->name,
+ 'issuer_id' => $this->issuerCompany->id,
+ 'amount' => (float) $this->amount,
+ 'service_charge' => (float) $this->amount,
+ 'currency' => new CurrencyResource($this->currency),
+ 'created_at' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A'),
+ 'currency_rate' => (float) $this->currency_rate,
+ 'status' => $this->status,
+ 'status_name' => ApprovalStatus::APPROVAL_STATUS_ID[$this->status],
+ 'payment_method' => (int)$this->payment_method,
+ 'payment_method_name' => ucwords(PaymentMethodType::PAYMENT_METHODS_ID[$this->payment_method]),
+ 'payment_reference' => $this->reference,
+ 'transactions_ids' => GroupTransactionsForOrderV2Resource::collection($this->groupTransactions)
+ ];
+ }
+}
diff --git a/app/Http/Resources/GroupTransactionsForOrderV2Resource.php b/app/Http/Resources/GroupTransactionsForOrderV2Resource.php
new file mode 100644
index 00000000..7beb49e7
--- /dev/null
+++ b/app/Http/Resources/GroupTransactionsForOrderV2Resource.php
@@ -0,0 +1,23 @@
+ $this->id,
+ 'group_id' => $this->group_id,
+ 'transaction_id' => $this->transaction_id,
+ ];
+ }
+}
diff --git a/app/Http/Resources/TransactionResource.php b/app/Http/Resources/TransactionResource.php
index e96681bc..60b36104 100644
--- a/app/Http/Resources/TransactionResource.php
+++ b/app/Http/Resources/TransactionResource.php
@@ -3,15 +3,14 @@
namespace App\Http\Resources;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
-use App\Classes\ValueObjects\Constants\DocumentType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Group;
-use App\Models\Order;
use App\Models\Transaction;
use App\Models\Wallet;
use Carbon\Carbon;
use Illuminate\Http\Resources\Json\JsonResource;
+
class TransactionResource extends JsonResource
{
/**
@@ -24,6 +23,8 @@ class TransactionResource extends JsonResource
{
$order = null;
$groupTransactions = null;
+ $group_payment_attempts = null;
+ $group_payment_expired = null;
if ($this->owner instanceof Transaction) {
if ($this->owner) {
@@ -35,6 +36,12 @@ class TransactionResource extends JsonResource
if ($this->owner) {
$order = new OrderResource($this->owner->owner);
}
+
+ if($this->groups){
+ $group_payment_attempts = GroupForOrderV2Resource::collection($this->groups->whereNotIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]));
+ $group_payment_expired = GroupForOrderV2Resource::collection($this->groupsWithTrashed->whereIn('status', [ApprovalStatus::EXPIRED]));
+ }
+
} else {
$group = Group::where('reference', $this->payment_reference)->first();
if ($group) {
@@ -48,7 +55,9 @@ class TransactionResource extends JsonResource
'owner_type' => $this->owner_type,
'order' => $order,
'group_transactions' => $groupTransactions,
- 'group_reference' => $groupTransactions ? $group->reference : null,
+ 'group_reference' => $groupTransactions ? ($group ? $group->reference : null ) : null,
+ 'groups_payment_attempts' => $group_payment_attempts,
+ 'groups_payment_expired' => $group_payment_expired,
'documents' => $groupTransactions ? DocumentResource::collection($this->documents->where('status', ApprovalStatus::PENDING_VERIFICATION)) : DocumentResource::collection($this->documents),
'type' => (int) $this->type,
'bill_no' => $this->bill_no,
@@ -83,6 +92,7 @@ class TransactionResource extends JsonResource
->get()
),
'remarks' => RemarkResource::collection($this->remarks),
+ 'storages' => $this->storages ? $this->storages : null, //from middleware
'expires_on' => Carbon::parse($this->expires_on)->format('d-m-Y h:s:i'),
'updated_at' => Carbon::parse($this->updated_at)->format('d-m-Y'),
'created_at' => Carbon::parse($this->created_at)->format('d-m-Y')
diff --git a/app/Models/Transaction.php b/app/Models/Transaction.php
index e8c3a68f..54b5b376 100644
--- a/app/Models/Transaction.php
+++ b/app/Models/Transaction.php
@@ -89,6 +89,14 @@ class Transaction extends AbstractModel implements Documentable, Transactionable
return $this->BelongsToMany(Group::class, GroupTransaction::class, 'transaction_id');
}
+ /**
+ * @return BelongsToMany
+ */
+ public function groupsWithTrashed(): BelongsToMany
+ {
+ return $this->BelongsToMany(Group::class, GroupTransaction::class, 'transaction_id')->withTrashed();;
+ }
+
public function convert_original_amount()
{
if($this->booking()->first()->fix_currency_id !== 1) {
diff --git a/config/logging.php b/config/logging.php
index 1aa06aa3..03e98722 100644
--- a/config/logging.php
+++ b/config/logging.php
@@ -54,6 +54,12 @@ return [
'days' => 14,
],
+ 'storage_invoices' => [
+ 'driver' => 'single',
+ 'path' => storage_path('logs/laravel_storage_invoices.log'),
+ 'level' => 'info',
+ ],
+
'slack' => [
'driver' => 'slack',
'url' => env('LOG_SLACK_WEBHOOK_URL'),
diff --git a/database/migrations/2023_11_13_140300_add_is_credit_term_to_company_connections.php b/database/migrations/2023_11_13_140300_add_is_credit_term_to_company_connections.php
new file mode 100644
index 00000000..cf5303c5
--- /dev/null
+++ b/database/migrations/2023_11_13_140300_add_is_credit_term_to_company_connections.php
@@ -0,0 +1,32 @@
+boolean('is_credit_term')->default(false);
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::table('company_connections', function (Blueprint $table) {
+ $table->dropColumn('is_credit_term');
+ });
+ }
+}
diff --git a/resources/assets/vue/components/companies/elements/CustomerPaymentBillingInnerComponent.vue b/resources/assets/vue/components/companies/elements/CustomerPaymentBillingInnerComponent.vue
index c2012cb7..19ca390a 100644
--- a/resources/assets/vue/components/companies/elements/CustomerPaymentBillingInnerComponent.vue
+++ b/resources/assets/vue/components/companies/elements/CustomerPaymentBillingInnerComponent.vue
@@ -6,7 +6,8 @@
You can view your invoices here and make payment.
Warehouse Storage Fee (Days): {{ storage.numberOfDaysExceeded }} x 3 x {{ storage.cbm }}CBM
-Warehouse Storage Fee applies ten days after goods arrival in Malaysia.
-Invoice Date
+Status
+Amount
+Billing Question
+Billing Question
+Warehouse Storage Fee: {{ storage.numberOfDaysExceeded }} Days x RM {{ storage.pricePerCBM}} x {{ storage.cbm }} cbm
+Invoice No
+Invoice Date
+Amount
+Payment Date
+Bill Number
+Please contact our customer service.
+Thank you for your payment. The amount paid has been successfully applied to your invoice.