From 76e3668563aa5e06b88232f0e10fc7fc14280579 Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Thu, 16 Nov 2023 22:40:26 +0800 Subject: [PATCH] 20231109 Meeting Feedback 1 Fixes for warehouse storage charges --- .../Eloquent/Filters/OrderByIdDesc.php | 20 ++ .../Eloquent/Filters/OrderByUpdatedAtDesc.php | 20 ++ .../ControllersLogic/CallbackBillplzLogic.php | 29 +- .../Processors/CallbackBillplzProcessor.php | 37 ++- .../Billplzs/Services/DeletesBillplzBill.php | 34 ++ .../ControllersLogic/FetchOrderV2Logic.php | 4 +- .../FetchContainersFromYdPortalProcessor.php | 2 +- ...ContainersUpdatesFromYdPortalProcessor.php | 2 +- .../ListTransactionsLogic.php | 18 +- ...eateStorageInvoiceTransactionProcessor.php | 207 +++++++----- app/Console/Commands/CheckStorageInvoices.php | 85 +++++ app/Console/Kernel.php | 5 + app/Http/Kernel.php | 1 + .../CheckForStorageInvoiceByGroup.php | 64 ++++ .../CheckForStorageInvoiceByOrderId.php | 5 +- .../CheckForStorageInvoiceByTransactions.php | 53 +++- .../Resources/GroupForOrderV2Resource.php | 39 +++ .../GroupTransactionsForOrderV2Resource.php | 23 ++ app/Http/Resources/TransactionResource.php | 16 +- app/Models/Transaction.php | 8 + config/logging.php | 6 + ..._is_credit_term_to_company_connections.php | 32 ++ .../CustomerPaymentBillingInnerComponent.vue | 44 ++- ...CustomerPaymentBillingSectionComponent.vue | 10 +- .../OrderProfileV2SectionComponent.vue | 48 ++- .../CustomerPaymentsBillingComponent.vue | 14 - ...stomerPaymentsBillingVariant2Component.vue | 297 ++++++++++++++++++ .../PaymentsBillingVariant2Components.vue | 110 +++++++ .../forms/GroupPaymentFormComponent.vue | 8 +- .../views/pages/payments_redirect.blade.php | 11 +- routes/transaction.php | 1 + 31 files changed, 1105 insertions(+), 148 deletions(-) create mode 100644 app/Classes/General/Eloquent/Filters/OrderByIdDesc.php create mode 100644 app/Classes/General/Eloquent/Filters/OrderByUpdatedAtDesc.php create mode 100644 app/Classes/Modules/Billplzs/Services/DeletesBillplzBill.php create mode 100644 app/Console/Commands/CheckStorageInvoices.php create mode 100644 app/Http/Middleware/CheckForStorageInvoiceByGroup.php create mode 100644 app/Http/Resources/GroupForOrderV2Resource.php create mode 100644 app/Http/Resources/GroupTransactionsForOrderV2Resource.php create mode 100644 database/migrations/2023_11_13_140300_add_is_credit_term_to_company_connections.php create mode 100644 resources/assets/vue/components/paymentsBilling/elements/CustomerPaymentsBillingVariant2Component.vue create mode 100644 resources/assets/vue/components/paymentsBilling/elements/PaymentsBillingVariant2Components.vue 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 @@
@@ -94,6 +95,10 @@ type: String, required: true }, + isPaidInvoices :{ + type: Boolean, + default: false + } }, data(){ return { @@ -117,7 +122,7 @@ }, selectedIds () { return this.selectedInvoice.map(s=>s.id); - }, + } }, methods: { generateSummaryInvoice(){ @@ -126,9 +131,40 @@ makePayment(){ this.submit(this.route('api.transaction.group.create', JSON.stringify(this.selectedId)), 'post', this.section, true, false); }, - updateList(packageList){ - this.selectedInvoice.includes(packageList) ? this.selectedInvoice.splice(this.selectedInvoice.indexOf(packageList), 1) : this.selectedInvoice.push(packageList); + updateList(invoices){ + invoices.forEach(invoice => { + if (this.selectedInvoice.includes(invoice)) { + this.selectedInvoice.splice(this.selectedInvoice.indexOf(invoice), 1); + } else { + this.selectedInvoice.push(invoice); + } + }); + }, + getMergedInvoices(shippingInvoice, storages){ + if(storages){ + const storageMap = {}; + for (const storage of storages) { + storageMap[storage.parentInvoiceId] = storage.storageInvoiceId; + } + + const storageInvoiceId = storageMap[shippingInvoice.id]; + const storage = storages.find((i) => { + return i.storageInvoiceId === storageInvoiceId; + }); + + const mergedArray = [ + ...(shippingInvoice ? [shippingInvoice] : []), + ...(storage && storage.storageInvoice.status !== 3 ? [storage.storageInvoice] : []) + ]; + return mergedArray; + } + + const mergedArray = [ + ...(shippingInvoice ? [shippingInvoice] : []) + ]; + return mergedArray; + } } } diff --git a/resources/assets/vue/components/companies/sections/CustomerPaymentBillingSectionComponent.vue b/resources/assets/vue/components/companies/sections/CustomerPaymentBillingSectionComponent.vue index 49f48d87..06a4ad5d 100644 --- a/resources/assets/vue/components/companies/sections/CustomerPaymentBillingSectionComponent.vue +++ b/resources/assets/vue/components/companies/sections/CustomerPaymentBillingSectionComponent.vue @@ -100,27 +100,27 @@
- +
- +
- +
- +
- +
diff --git a/resources/assets/vue/components/orders/sections/OrderProfileV2SectionComponent.vue b/resources/assets/vue/components/orders/sections/OrderProfileV2SectionComponent.vue index 271bc1f1..ed2e2e57 100644 --- a/resources/assets/vue/components/orders/sections/OrderProfileV2SectionComponent.vue +++ b/resources/assets/vue/components/orders/sections/OrderProfileV2SectionComponent.vue @@ -147,9 +147,12 @@

You can view your invoices here and make payment.

-
-
- +
+
+ +
+
+
@@ -180,6 +183,16 @@ computed: { 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; } }, watch: { @@ -202,16 +215,35 @@ this.isLoading = false; this.order = response.payload.data; }, - getStorage(invoice) { - const storageObject = this.findStorageObject(invoice.id); + getStorageInfo(invoice) { + const storageObject = this.findStorageInfoObject(invoice.id); return storageObject; }, - findStorageObject(storageInvoiceId) { + findStorageInfoObject(shippingInvoiceId) { if(this.order.storages){ - return this.order.storages.find(storage => storage.storageInvoiceId === storageInvoiceId); + 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; + }); + + return storageInvoice; + }, } } diff --git a/resources/assets/vue/components/paymentsBilling/elements/CustomerPaymentsBillingComponent.vue b/resources/assets/vue/components/paymentsBilling/elements/CustomerPaymentsBillingComponent.vue index 42d3b229..45a06c47 100644 --- a/resources/assets/vue/components/paymentsBilling/elements/CustomerPaymentsBillingComponent.vue +++ b/resources/assets/vue/components/paymentsBilling/elements/CustomerPaymentsBillingComponent.vue @@ -1,17 +1,6 @@