Compare commits

...

33 Commits

Author SHA1 Message Date
edmondlang 924f4f2ace fix qr api issue 2024-04-10 22:27:09 +08:00
edmondlang 6369282b38 update qr code config 2024-04-10 18:22:11 +08:00
jiasheng224 1991cf2c57 fix qr api issue 2024-04-09 17:42:10 +08:00
Omair Saleh e5347f56b7 change bank in details 2024-04-04 08:22:47 +08:00
Omair Saleh 6673a44137 fix invoice date for april 2024-04-03 12:22:32 +08:00
Omair Saleh 4d3345f613 Merge remote-tracking branch 'origin/master' 2024-04-03 12:17:54 +08:00
Omair Saleh 60b8657773 fix invoice date for april 2024-04-03 12:17:40 +08:00
edmondlang 9f7a8d0d4b hide deletePaidGroupTransaction 2024-03-31 23:12:38 +08:00
edmondlang a87ab6c27f logging delete paid group transaction 2024-03-31 21:41:42 +08:00
edmondlang 462a4776cd delete paid group transaction 2024-03-31 17:36:12 +08:00
edmondlang 7e029c5610 delete paid group transaction 2024-03-30 00:49:55 +08:00
edmondlang 0719285286 show all extra payments from customer 2024-03-29 00:59:30 +08:00
edmondlang 64400d1524 fix ExportsCustomersWalletTransactionHistory 2024-03-29 00:06:22 +08:00
edmondlang be0279f56b fix ExportsCustomersWalletTransactionHistory 2024-03-29 00:02:13 +08:00
Dillon Ngo e15170bc7f Merge branch 'dillon/46.9-warehouse-storage-charges-fixes' into 'master'
Multiple fixes related to storage invoices

See merge request CIEFWorldwideSdnBhd/shipping-portal!212
2024-03-26 00:44:33 +00:00
Dillon Ngo 59f527aee7 Enable back manual payment that was temporary disable at order page for invoices with storage fee 2024-03-26 08:10:34 +08:00
Dillon Ngo d7aa248972 Merge branch 'dillon/55-billplz-fix' into 'master'
Update info log location for vue polling related stuff + perfexcrm integration

See merge request CIEFWorldwideSdnBhd/shipping-portal!211
2024-03-18 12:17:11 +00:00
Dillon Ngo 1679d1ecf4 Fix a problem of unsuccessful payment when shipping invoice is paid first before storage invoice appear 2024-03-16 15:49:02 +08:00
Dillon Ngo 7ca48e9638 Fix a problem in info display inaccurate in payment history for manual payment 2024-03-16 15:17:28 +08:00
Dillon Ngo 14278a888a Merge branch 'dillon/55-billplz-fix' into 'master'
Long term solution to prevent customer making payment to a shipping invoice...

See merge request CIEFWorldwideSdnBhd/shipping-portal!210
2024-03-16 05:52:58 +00:00
Dillon Ngo 5de2554d63 Fix a problem with storage invoice checking when a payment related transaction is deleted at order page 2024-03-15 03:33:58 +08:00
edmondlang 033a835fce update SendPermitsReminderEmails logging 2024-03-14 12:48:25 +08:00
edmondlang 66ddb5da23 update send permits reminder 2024-03-14 12:46:47 +08:00
edmondlang f95545a985 update container remark in order page 2024-03-13 00:20:39 +08:00
edmondlang 9e8685bd02 update container remark in order page 2024-03-13 00:02:52 +08:00
edmondlang 1224735ba8 Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal 2024-03-12 23:52:22 +08:00
edmondlang 11e2390059 update container and container remarks 2024-03-12 23:52:07 +08:00
Dillon Ngo c280da36d7 Merge branch 'dillon/55-billplz-fix' into 'master'
Fix a problem reported by Yien where order shipping invoice pending payment despite payment made

See merge request CIEFWorldwideSdnBhd/shipping-portal!209
2024-03-12 06:32:13 +00:00
Dillon Ngo f1b8c6a556 When a pending verification group payment is deleted, do not display the group with no payment transaction(group payment) 2024-03-09 02:20:34 +08:00
Dillon Ngo 6d210d3713 Fix a problem with deleting a pending verification group payment at order page 2024-03-09 02:16:32 +08:00
Dillon Ngo 5dd2df02fd Hide 'Make Payment' button when there is a group payment pending verification from Admin 2024-03-09 01:22:13 +08:00
Dillon Ngo b207b11336 Fix missing group payment info on order page 2024-03-08 23:53:54 +08:00
Dillon Ngo ffd95ee1cc Fix missing group payment info on order page 2024-03-08 23:31:37 +08:00
35 changed files with 632 additions and 70 deletions
@@ -80,12 +80,13 @@ class CallbackBillplzProcessor
if ($group) {
foreach ($group->groupTransactions as $groupTransaction) {
$invoice = $groupTransaction->transaction;
if($invoice->status !== ApprovalStatus::COMPLETED){
$paymentTransaction = $this->createPaymentTransactionProcessor->execute($invoice, PaymentMethodType::WALLET, null, false);
$paymentTransaction = $this->createPaymentTransactionProcessor->execute($invoice, PaymentMethodType::WALLET, null, false);
if($paymentTransaction && $paymentTransaction->status == ApprovalStatus::APPROVED){
$pL = $invoice->owner;
$this->releaseGoodsToCustomerProcessor->execute($pL, $invoice);
if($paymentTransaction && $paymentTransaction->status == ApprovalStatus::APPROVED){
$pL = $invoice->owner;
$this->releaseGoodsToCustomerProcessor->execute($pL, $invoice);
}
}
}
@@ -111,7 +112,9 @@ class CallbackBillplzProcessor
foreach ($group->groupTransactions as $groupTransaction) {
$invoice = $groupTransaction->transaction;
$totalAmountToBePaid += $invoice->amount;
if($invoice->status !== ApprovalStatus::COMPLETED){
$totalAmountToBePaid += $invoice->amount;
}
}
if(($totalAmountToBePaid - $actualAmountPaid) < 0.01){
@@ -70,15 +70,31 @@ class ExportsCustomersWalletTransactionHistory implements FromQuery, WithHeading
$description = 'Credit Voucher for ' . $transaction->payment_reference;
break;
case TransactionType::PAYMENT:
$booking = Transaction::where('payment_reference', $transaction->bill_no)->first()->owner;
if (!$booking) {
$description = 'Payment for unknown booking, please contact tech support.';
$payment = Transaction::where('payment_reference', $transaction->bill_no)->first();
if (!$payment) {
$description = 'Payment not found, please contact tech support.';
break;
}
$marking = $booking->marking;
$description = 'Payment For booking refs' . $marking;
$invoice = $payment->owner;
if (!$invoice) {
$description = 'Invoice not found, please contact tech support.';
break;
}
$packingList = $invoice->owner;
if (!$packingList) {
$description = 'Packing List not found, please contact tech support.';
break;
}
$order = $packingList->owner;
if (!$order) {
$description = 'Order not found, please contact tech support.';
break;
}
$description = 'Payment For booking refs ' . $order->reference;
break;
case TransactionType::DEBIT_NOTE:
$description = 'Debit Voucher for ' . $transaction->payment_reference;
@@ -48,6 +48,8 @@ class DeleteGroupLogic extends AbstractControllerLogic
*/
public function logic(Request $request) : JsonResponse
{
ini_set('memory_limit', '-1');
$group = $this->fetchesGroup->execute(['id' => $request->route('id')]);
foreach ($group->groupTransactions as $groupTransaction) {
@@ -0,0 +1,90 @@
<?php
namespace App\Classes\Modules\Transactions\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\General\Eloquent\Filters\PaymentMethod;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\Modules\Transactions\Services\FetchesGroup;
use App\Classes\Modules\Transactions\Services\DeletesTransaction;
use App\Classes\Modules\Transactions\Services\DeletesGroup;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Transaction;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class DeletePaidGroupLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification(): array
{
return [
'title' => 'Delete Paid Group Transaction',
'message' => 'You have successfully deleted this Group Transaction'
];
}
/** @var FetchesGroup */
private $fetchesGroup;
/** @var DeletesGroup */
private $deletesGroup;
/**
* DeleteGroupLogic constructor.
* @param updatesTransactionStatus $updatesTransactionStatus
* @param FetchesGroup $fetchesGroup
* @param DeletesTransaction $deletesTransaction
*/
public function __construct(FetchesGroup $fetchesGroup, DeletesGroup $deletesGroup)
{
$this->fetchesGroup = $fetchesGroup;
$this->deletesGroup = $deletesGroup;
}
/**
* @param Request $request
* @return JsonResponse
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function logic(Request $request): JsonResponse
{
$group = $this->fetchesGroup->execute(['id' => $request->route('id')]);
foreach ($group->groupTransactions as $groupTransaction) {
$invoice = $groupTransaction->transaction;
$paymentTransaction = $invoice->transactions()->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->first();
if ($paymentTransaction->payment_method == PaymentMethodType::WALLET) {
// Store the transaction ID before deleting
$transactionId = Transaction::where('bill_no', $paymentTransaction->payment_reference)->first()->id;
// Delete the transaction
Transaction::where('id', $transactionId)->first()->delete();
// Now you have the transaction ID available in $transactionId
Log::channel('deletePaidGroupOrder')->info("Deleted payment reference transaction ID: " . $transactionId);
} else {
Log::channel('deletePaidGroupOrder')->info("no transaction found. Invoice Id ->" . $invoice->id);
}
// Store the transaction ID before deleting
$transactionId = $paymentTransaction->id;
// Delete the payment transaction
$paymentTransaction->delete();
Log::channel('deletePaidGroupOrder')->info("Deleted payment transaction ID: " . $transactionId);
}
Log::channel('deletePaidGroupOrder')->info("Deleted Group -> " . $group->id);
$this->deletesGroup->execute($group);
return $this->response([]);
}
}
@@ -6,9 +6,13 @@ namespace App\Classes\Modules\Transactions\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Transactions\Services\FetchesTransaction;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\Modules\Transactions\Services\FetchesGroup;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Models\Transaction;
use App\Models\Wallet;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class DeletePaymentTransactionLogic extends AbstractControllerLogic
{
@@ -23,6 +27,9 @@ class DeletePaymentTransactionLogic extends AbstractControllerLogic
];
}
/** @var FetchesGroup */
private $fetchesGroup;
/** @var FetchesTransaction */
private $fetchesTransaction;
@@ -34,11 +41,13 @@ class DeletePaymentTransactionLogic extends AbstractControllerLogic
* SuspendTransactionLogic constructor.
* @param FetchesTransaction $fetchesTransaction
* @param UpdatesTransactionStatus $updatesTransactionStatus
* @param FetchesGroup $fetchesGroup
*/
public function __construct(FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus)
public function __construct(FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, FetchesGroup $fetchesGroup)
{
$this->fetchesTransaction = $fetchesTransaction;
$this->updatesTransactionStatus = $updatesTransactionStatus;
$this->fetchesGroup = $fetchesGroup;
}
@@ -46,11 +55,23 @@ class DeletePaymentTransactionLogic extends AbstractControllerLogic
{
$transaction = $this->fetchesTransaction->execute(['id' => $request->route('id')]);
if($transaction->owner instanceof Wallet){
try{
$group = $this->fetchesGroup->execute(['reference' => $transaction->payment_reference]);
$group->status = ApprovalStatus::SUSPENDED;
$group->save();
}
catch(\Exception $excaption){
Log::info('No group associated with transaction with payment_reference - '.$transaction->payment_reference);
}
}
$transaction->delete();
$invoice = $transaction->owner;
$this->updatesTransactionStatus->execute($invoice, ApprovalStatus::APPROVED);
if ($invoice instanceof Transaction) {
$this->updatesTransactionStatus->execute($invoice, ApprovalStatus::APPROVED);
}
return $this->response([]);
}
@@ -328,7 +328,7 @@ class CheckStorageInvoiceTransactionProcessor
private function updatePaymentTransactionViaGroupPayment($storageInvoice){
Log::channel('storage_invoices')->info('updatePaymentTransactionViaGroupPayment');
$groups = $storageInvoice->groups()->get();
$groups = $storageInvoice->groups()->whereNotIn('status', [ApprovalStatus::COMPLETED, ApprovalStatus::SUSPENDED])->get();
foreach ($groups as $grp){
$groupReference = $grp->reference;
$walletTransaction = $this->fetchesTransaction->execute(['payment_reference' => $groupReference]);
@@ -5,8 +5,10 @@ namespace App\Classes\Modules\Transactions\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Classes\General\Eloquent\AbstractUpdateRelationshipRecord;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\PackingList;
use App\Models\Transaction;
use Carbon\Carbon;
class CreatesTransaction extends AbstractUpdateRelationshipRecord
{
@@ -33,6 +35,11 @@ class CreatesTransaction extends AbstractUpdateRelationshipRecord
$model->expires_on = $object->getExpiresOn();
$model->status = $object->getStatus();
if((int)$object->getTransactionType() === TransactionType::SHIPPING_INVOICE){
$model->created_at = Carbon::now()->subDays(10);
$model->updated_at = Carbon::now()->subDays(10);
}
return $this->handler($packing_list->transactions(), $model);
}
}
}
@@ -7,6 +7,7 @@ use App\Models\PermitsReminder;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
class SendPermitsReminderEmails extends Command
{
@@ -41,23 +42,23 @@ class SendPermitsReminderEmails extends Command
*/
public function handle()
{
$now = now();
$startRange = $now->subDays(3)->startOfDay();
$endRange = $now->copy()->addDays(6)->endOfDay();
$currentDateTime = now();
$startRange = $currentDateTime->subDays(3)->startOfDay();
$endRange = $currentDateTime->copy()->addDays(6)->endOfDay();
$reminders = PermitsReminder::whereDate('reminder_date', '>=', $startRange)
->whereDate('reminder_date', '<=', $endRange)
->orWhere('reminder_date', '<', now())
->pluck('model');
$this->info($this->getTimeStamp() . json_encode($reminders));
if ($reminders->isEmpty()) {
$this->info('No reminders expiring within the specified range.');
return;
}
$users = User::whereIn(
'email',
[
'edmond.wuiming2021@gmail.com',
'anithagurl96@gmail.com'
]
)->get();
$this->info($this->getTimeStamp() . 'Reminders: ' . $reminders->toJson());
$users = User::whereIn('email', $this->getEmailList())->get();
foreach ($users as $user) {
$this->info($this->getTimeStamp() . 'Reminder email sent to ' . $user->email);
@@ -71,4 +72,12 @@ class SendPermitsReminderEmails extends Command
{
return '[' . Carbon::now()->format('Y-m-d H:i:s') . '] - ';
}
protected function getEmailList(): array
{
return [
'edmond.wuiming2021@gmail.com',
'anithagurl96@gmail.com'
];
}
}
@@ -3,6 +3,7 @@
namespace App\Http\Controllers\PermitsReminder;
use App\Models\PermitsReminder;
use Carbon\Carbon;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -15,14 +16,25 @@ class ListPermitsReminderController
public function list(Request $request): JsonResponse
{
$perPage = 10; // Number of items per page
$page = request('page', 1); // Get the current page from the request
$page = $request->query('page', 1); // Get the current page from the request
// Paginate the PermitsReminder model
$query = PermitsReminder::orderBy('id', 'desc');
$paginator = $query->paginate($perPage, ['*'], 'page', $page);
$paginator = PermitsReminder::orderBy('reminder_date')->paginate($perPage, ['*'], 'page', $page);
// Convert paginated data to an array
// Get current date and time
$currentDateTime = now();
// Define date range
$startRange = $currentDateTime->subDays(3)->startOfDay();
$endRange = $currentDateTime->copy()->addDays(6)->endOfDay();
// Process paginated items
$data = $paginator->items();
foreach ($data as &$item) {
// Check if the reminder_date is within the date range or after the current date
$reminderDate = Carbon::parse($item->reminder_date);
$item->show_remind = $reminderDate->between($startRange, $endRange) || $reminderDate->isBefore($currentDateTime);
}
// Create pagination links
$links = [
@@ -32,6 +44,7 @@ class ListPermitsReminderController
"next" => $paginator->nextPageUrl(),
];
// Prepare response
$response = [
"title" => "List Permits Reminder",
"message" => "You have successfully retrieved a list of Permits Reminder",
@@ -0,0 +1,20 @@
<?php
namespace App\Http\Controllers\Transactions;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use App\Classes\Modules\Transactions\ControllersLogic\DeletePaidGroupLogic;
class DeletePaidGroupController
{
/**
* @param Request $request
* @param DeleteGroupTransactionLogic $logic
* @return JsonResponse
*/
public function delete(Request $request, DeletePaidGroupLogic $logic) : JsonResponse {
return $logic->execute($request);
}
}
+14 -6
View File
@@ -23,17 +23,25 @@ class ContainerResource extends JsonResource
'container_specification' => ContainerTypes::CONTAINER_SPECIFICATION[$this->container_type],
'container_number' => $this->container_number,
'seal_reference' => $this->seal_reference,
'loading_date' => $this->loading_date ? $this->loading_date->format('d-m-Y') : $this->loading_date,
'loading_date' => optional($this->loading_date)->format('d-m-Y'),
'transport' => new TransportResource($this->transports()->first()),
'packages_count' => $this->packages()->where('packages.type', '!=', 2)->sum('quantity'),
'total_cbm' => $this->packages()->sum(DB::raw('(width/100) * (height/100) * (length/100) * quantity')),
'remarks' => RemarkResource::collection($this->remarks),
'status' => $this->status,
'packing_lists' => $this->whenLoaded('packingLists', PackingListResource::collection($this->whenLoaded('packingLists', function(){
return $this->packingLists()->get()->sortBy(function ($packingList) {
return $packingList->owner->company_module_id;
});
})))
'packing_lists' => $this->shouldIncludePackingListData($request) ? $this->getSortedPackingLists() : null,
];
}
protected function shouldIncludePackingListData($request)
{
return (isset($request->all()['with_packing_list_data']) && ($request->all()['with_packing_list_data'] == false)) ? false : true;
}
protected function getSortedPackingLists()
{
return $this->whenLoaded('packingLists', PackingListResource::collection(
$this->packingLists()->get()->sortBy(fn ($packingList) => $packingList->owner->company_module_id)
));
}
}
@@ -40,8 +40,10 @@ class GroupForOrderV2Resource extends JsonResource
'payment_transaction' => $payment_transaction ? [
'id' => $payment_transaction->id,
'status' => $payment_transaction->status,
'status_name' => ApprovalStatus::APPROVAL_STATUS_ID[$payment_transaction->status]
] : []
'status_name' => ApprovalStatus::APPROVAL_STATUS_ID[$payment_transaction->status],
'bill_no' => $payment_transaction->bill_no,
'updated_at' => Carbon::parse($payment_transaction->updated_at)->format('d-m-Y h:i:s A'),
] : null
];
}
}
+1 -1
View File
@@ -78,7 +78,7 @@ class TransactionResource extends JsonResource
->get()
),
'remarks' => RemarkResource::collection($this->remarks),
'expires_on' => Carbon::parse($this->expires_on)->format('d-m-Y h:s:i'),
'expires_on' => Carbon::parse($this->expires_on)->format('d-m-Y h:i:s A'),
'updated_at' => Carbon::parse($this->updated_at)->format('d-m-Y'),
'created_at' => Carbon::parse($this->created_at)->format('d-m-Y')
];
@@ -121,7 +121,7 @@ class TransactionWithStorageResource extends JsonResource
'remarks' => RemarkResource::collection($this->remarks),
'storages' => $this->storages ? $this->storages : null, //from middleware
'is_waived' => (int) $this->is_waived,
'expires_on' => Carbon::parse($this->expires_on)->format('d-m-Y h:s:i'),
'expires_on' => Carbon::parse($this->expires_on)->format('d-m-Y h:i:s A'),
'updated_at' => Carbon::parse($this->updated_at)->format('d-m-Y'),
'created_at' => Carbon::parse($this->created_at)->format('d-m-Y')
];
+6
View File
@@ -113,6 +113,12 @@ return [
'level' => 'info',
],
'deletePaidGroupOrder' => [
'driver' => 'single',
'path' => storage_path('logs/deletePaidGroupOrder.log'),
'level' => 'info',
],
'vue_polling' => [
'driver' => 'single',
'path' => storage_path('logs/laravel_vue_plling.log'),
+8
View File
@@ -0,0 +1,8 @@
<?php
return [
// please update resources/assets/vue/app.js if value is changed
// 'qr_code_img_url' => 'https://chart.googleapis.com/chart?chs=150x150&cht=qr&chl=', // not working
'qr_code_img_url' => 'https://qrcode.tec-it.com/API/QRCode?data=',
];
+3
View File
@@ -24,6 +24,9 @@ import closable from './general/directives/closable';
import Avatar from 'vue-avatar';
// define global variable
Vue.prototype.$qr_code_img_url = 'https://qrcode.tec-it.com/API/QRCode?data=';
/** Application Injections */
Vue.use(vuelidate);
Vue.use(VueTheMask);
@@ -1,5 +1,5 @@
<template>
<div class="row m-t-5">
<div class="row m-t-5" @keyup.enter="submitForm">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.content">
<input type="text" class="form-control fs-12" placeholder="Write your comments..." v-model.trim="parameters.content">
@@ -42,7 +42,7 @@
submitForm() {
this.submit(this.data ? this.route('api.remark.update', this.data.id) : this.route('api.packing_list.container.remark.create', this.id), this.data ? 'put' : 'post', this.section, true, true);
this.$emit('submit')
}
},
},
mixins: [modalFormHandler]
}
@@ -0,0 +1,229 @@
<template>
<div class="row">
<div class="col">
<div class="row" v-if="container">
<div class="col">
<div class="row align-items-center m-t-10">
<div class="col bg-master-lightest rounded padding-20 m-l-10 m-r-10">
<div class="row d-flex justify-content-between align-items-center">
<div class="col b-r">
<div class="row">
<div class="col">
<p class="m-b-0 large-text normal m-b-10">Container Number</p>
</div>
</div>
<div class="row">
<div class="col">
<p class="m-t-0 m-b-0 fs-20 bold">{{ container.container_reference }}</p>
<p class="m-t-0 m-b-0 small-text">{{ container.container_number }}</p>
<p class="m-t-0 m-b-0 small-text">seal number</p>
</div>
</div>
</div>
<div class="col">
<div class="row">
<div class="col">
<p class="fs-10 bold m-b-0">ETD</p>
<p class="small-text m-t-0">{{ container.transport.current_schedule.etd }} <a class="b-rad-none all-caps requestModal" data-type="rescheduleDate"><i class="fa fa-edit pointer fa-fw fs-15 m-l-5"></i></a>
</p>
</div>
</div>
<div class="row">
<div class="col">
<p class="fs-10 bold m-b-0">ETA</p>
<p class="small-text m-t-0">{{ container.transport.current_schedule.eta }} <a class="b-rad-none all-caps requestModal" data-type="rescheduleDate"><i class="fa fa-edit pointer fa-fw fs-15 m-l-5"></i></a>
</p>
</div>
</div>
</div>
<div class="col">
<div class="row">
<div class="col">
<p class="fs-10 bold m-b-0">Location</p>
<p class="small-text m-t-0">-tbc-</p>
</div>
</div>
<div class="row">
<div class="col">
<p class="fs-10 bold m-b-0">Destination</p>
<p class="small-text m-t-0">-tbc-</p>
</div>
</div>
</div>
<div class="col">
<div class="row">
<div class="col">
<p class="fs-10 bold m-b-0">Container Type</p>
<p class="small-text m-t-0">{{ container.container_specification.name }}</p>
</div>
</div>
<div class="row">
<div class="col">
<p class="fs-10 bold m-b-0">Owner</p>
<p class="small-text m-t-0">-tbc-</p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row m-t-10 m-b-50">
<div class="col">
<div class="row">
<div class="col">
<div class="row h-100">
<div class="col">
<h5 class="m-b-5 large-text bold l-20">Tracking:</h5>
<div class="row padding-10">
<div class="col rounded bg-master-lighter padding-15">
<li class="m-t-10">
<a class="btn btn-sm btn-primary b-rad-none all-caps requestModal"
data-type="containerDepature">Container Departure</a>
</li>
<li class="m-t-10">
<a class="btn btn-sm btn-primary b-rad-none all-caps requestModal"
data-type="containerArrival">Arrival Date</a>
</li>
<li class="m-t-10">
<a class="btn btn-sm btn-primary b-rad-none all-caps requestModal"
data-type="containerUnpacking">Date of Unpacking</a>
</li>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in"
type="rescheduleDate">
<reschedule-date-form-component :section="section"
:data="container"></reschedule-date-form-component>
</modal-component>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in"
type="containerDepature">
<container-depature-form-component :section="section"
:data="container"></container-depature-form-component>
</modal-component>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in"
type="containerArrival">
<container-arrival-form-component :section="section"
:data="container"></container-arrival-form-component>
</modal-component>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in"
type="containerUnpacking">
<container-unpacking-form-container :section="section"
:data="container"></container-unpacking-form-container>
</modal-component>
<div class="row m-t-10">
<div class="col">
<div class="row">
<div class="col-auto padding-5 m-l-15 m-r-15 pointer" :class="[{ 'text-primary': tabShowing === 'Comments' }, { 'b-b': tabShowing === 'Comments' }]" @click="tabShowing = 'Comments'">
<h5 class="large-text bold l-20" :class="[{ 'text-primary': tabShowing === 'Comments' }]"> Comments</h5>
</div>
<!-- <div class="col-auto padding-5 m-l-15 m-r-15 pointer" :class="[{ 'text-primary': tabShowing === 'Timeline' }, { 'b-b': tabShowing === 'Timeline' }]" @click="tabShowing = 'Timeline'">
<h5 class="large-text bold l-20" :class="[{ 'text-primary': tabShowing === 'Timeline' }]"> Activity Timeline</h5>
</div> -->
</div>
<div class="row p-l-10 p-r-10">
<div class="col rounded padding-15">
<div class="row" v-if="tabShowing === 'Comments'">
<div class="col">
<div class="row" v-for="remarks in container.remarks">
<div class="col">
<container-comment-component :section="section" :data="remarks"></container-comment-component>
</div>
</div>
<container-comment-form-component :section="section" :id="container.id"></container-comment-form-component>
</div>
</div>
<div class="row" v-if="tabShowing === 'Timeline'">
<div class="col">
<div class="row align-items-center justify-content-center p-t-50 p-b-50">
<div class="col-10">
<div class="row align-items-center justify-content-center hint-text">
<div class="col-4 hint-text"><img src="/images/not-found-illustration.png" class="w-100 hint-text"/></div>
</div>
<div class="row text-center">
<div class="col">
<div class="row m-t-20">
<div class="col">
<p class="all-caps no-margin fs-11" style="letter-spacing: 2px;">Nothing To Show Here</p>
</div>
</div>
<div class="row m-t-5 align-items-center justify-content-center hide">
<div class="col">
<small class="fs-9 muted all-caps font-lato" style="letter-spacing: 2px">There is no results found, Try adjusting your filters to find what you are looking for.</small>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
id: {
type: Number,
required: true,
}
},
data() {
return {
section: 'containerPofileSection',
isLoading: true,
container: null,
expanded: false,
CBMcapacity: 30,
// tabShowing: 'Timeline',
tabShowing: 'Comments',
selectAllPackingList: false,
selectedPackageList: [],
deleteCommentId: '',
}
},
computed: {
pendingQueue() {
return this.$store.getters.isInCompleteQueue(this.section);
},
loadedCBM() {
return (Math.ceil((this.container.packing_lists.reduce((total, obj) => total + obj.packages.reduce((total, obj) => obj.cbm + total, 0), 0)) * 1000) / 1000).toFixed(3)
},
},
watch: {
pendingQueue(inComplete) {
if (inComplete) {
this.fetchCompany();
}
}
},
created() {
this.$store.dispatch('updateListQueue', { 'name': this.section });
},
methods: {
fetchCompany() {
this.isLoading = true;
this.submit(route('api.packing_list.container.show', this.id) + '?with_packing_list_data=0', 'get', this.section, false, false)
},
successHandler(response) {
this.$store.dispatch('completeList', { 'name': this.section, 'data': [] });
this.isLoading = false;
this.container = response.payload.data;
},
}
}
</script>
@@ -7,7 +7,8 @@
<div class="col">
<a :href="route('order.qr.download', item.id)" target="_blank">
<div class="peelable-corner overflow-hidden relative">
<img :src="'https://chart.googleapis.com/chart?chs=150x150&cht=qr&chl={id:'+item.id+'}'" class="w-100">
<!-- <img :src="'https://chart.googleapis.com/chart?chs=150x150&cht=qr&chl={id:'+item.id+'}'" class="w-100"> -->
<img :src="this.$qr_code_img_url + item.id + '}'" class="w-100">
</div>
</a>
</div>
@@ -47,7 +47,7 @@
</div>
</div>
</div>
<div class="row b-b b-grey p-b-20 align-items-center">
<div class="row b-b b-grey p-b-20 align-items-center parentContainer">
<div class="col">
<div class="row m-b-5">
<div class="col-auto">
@@ -58,9 +58,48 @@
<small class="fs-10 all-caps muted">Status</small>
<p class="no-margin bold">{{item.container ? item.container.transport.schedule_complete && status === 'Shipping' ? 'Custom Clearance' : status : status}}</p>
</div>
<div class="col-auto" v-if="$store.getters.isAdmin">
<small class="fs-10 all-caps muted">Container</small>
<p class="no-margin bold">{{item.container ? item.container.container_reference : '-'}}</p>
<div class="col" v-if="$store.getters.isAdmin">
<div class="row h-100 justify-content-center align-items-center">
<div class="col">
<small class="fs-10 all-caps muted">Container</small>
<p class="no-margin bold">{{ item.container ? item.container.container_reference : '-' }}</p>
</div>
<div class="col-auto" v-if="$store.getters.isAdmin && item.container">
<i class="fa fa-comment fs-15 pointer requestModal" data-type="commentsModal"></i>
<modal-component type="commentsModal" styleType="fill-in">
<div class="row">
<div class="col bg-white b-rad-lg p-t-10 p-t-10 p-l-40 p-r-40">
<h4 class="m-b-20">Remarks</h4>
<div class="row" v-if="item.container.remarks.length">
<div class="col">
<div class="row" v-for="remarks in item.container.remarks">
<div class="col">
<container-comment-component :section="section" :data="remarks"></container-comment-component>
</div>
</div>
</div>
</div>
<div class="row align-items-center justify-content-center p-t-50 p-b-50" v-else>
<div class="col-10">
<div class="row align-items-center justify-content-center hint-text">
<div class="col-4 hint-text"><img src="/images/not-found-illustration.png" class="w-100 hint-text"/></div>
</div>
<div class="row text-center">
<div class="col">
<div class="row m-t-20">
<div class="col">
<p class="all-caps no-margin fs-11" style="letter-spacing: 2px;">Nothing To Show Here Yet!</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</modal-component>
</div>
</div>
</div>
</div>
<div class="row">
@@ -12,7 +12,8 @@
<div class="col-10">
<a :href="route('order.qr.download', order.id)" target="_blank">
<div class="peelable-corner overflow-hidden relative">
<img :src="'https://chart.googleapis.com/chart?chs=150x150&cht=qr&chl={id:'+order.id+'}'" class="w-100">
<!-- <img :src="'https://chart.googleapis.com/chart?chs=150x150&cht=qr&chl={id:'+order.id+'}'" class="w-100"> -->
<img :src="this.$qr_code_img_url + order.id + '}'" class="w-100">
</div>
</a>
</div>
@@ -12,7 +12,8 @@
<div class="col-10">
<a :href="route('order.qr.download', order.id)" target="_blank">
<div class="peelable-corner overflow-hidden relative">
<img :src="'https://chart.googleapis.com/chart?chs=150x150&cht=qr&chl={id:'+order.id+'}'" class="w-100">
<!-- <img :src="'https://chart.googleapis.com/chart?chs=150x150&cht=qr&chl={id:'+order.id+'}'" class="w-100"> -->
<img :src="this.$qr_code_img_url + order.id + '}'" class="w-100">
</div>
</a>
</div>
@@ -277,11 +277,11 @@
<div class="font-heading fs-12">MYR {{(Math.round((totalOutstanding + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}</div>
</div>
</div>
<div class="row m-t-20" v-if="totalOutstanding - totalFloating > 0.009">
<div class="row m-t-20" v-if="totalOutstanding - totalFloating > 0.009 && !groupPaymentPending">
<div class="col">
<div class="btn btn-sm all-caps b-rad-none btn-success btn-block requestModal" data-type="makePayment">Make Payment</div>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="makePayment">
<group-payment-form-component :section="section" :selectedIds="selectedIds" :sumAmount="totalOutstanding.toFixed(2)" :showManualPayment="false"></group-payment-form-component>
<group-payment-form-component :section="section" :selectedIds="selectedIds" :sumAmount="totalOutstanding.toFixed(2)" :showManualPayment="true"></group-payment-form-component>
</modal-component>
</div>
</div>
@@ -345,6 +345,20 @@
});
return ids;
},
groupPaymentPending(){
if (Array.isArray(this.items)) {
for (let i = 0; i < this.items.length; i++) {
for (let j = 0; j < this.items[i].groups_payment_history.length; j++) {
const item = this.items[i].groups_payment_history[j];
// console.log('item', JSON.stringify(item));
if (item.payment_transaction && item.payment_transaction.status === 1) {
return true;
}
}
}
}
return false;
}
},
methods: {
getLatestComment(item) {
@@ -356,6 +370,7 @@
},
groupTransactionsExist(items, groups) {
return groups.some(group =>
group.payment_transaction &&
group.transactions_ids.length === items.length &&
group.transactions_ids.every(transaction =>
items.some(item => item.id === transaction.transaction_id)
@@ -25,12 +25,12 @@
<i class="fa fa-repeat fs-20 text-white"></i>
</div>
</div>
<div class="col-auto requestModal" v-if="item.status != 2 && item.status != 6" data-type="deleteGroupTransaction">
<div class="col-auto requestModal" v-if="item.status != 2 && item.status != 6" data-type="deleteGroupTransactionInProgress">
<div class="btn bg-grey no-border">
<i class="fa fa-times"></i>
</div>
</div>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="deleteGroupTransaction">
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="deleteGroupTransactionInProgress">
<general-confirmation-form-component
contentText="Are you sure you want to delete this Group Payment?"
modalType="delete"
@@ -75,6 +75,23 @@
<i class="fa fa-repeat fs-20 text-white"></i>
</div>
</div>
<!-- <div class="col-auto requestModal" v-if="item.status == 2 && $store.getters.isSuperAdmin && false" data-type="deletePaidGroupTransaction">
<div class="btn bg-grey no-border">
<i class="fa fa-times"></i>
</div>
</div> -->
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="deletePaidGroupTransaction">
<general-confirmation-form-component
contentText="Are you sure you want to delete this Paid Group Payment?"
modalType="delete"
buttonText="Delete"
class="text-center"
:apiRoute="route('api.transaction.group.paidGroup.delete', item.id)"
apiMethod="delete"
:section="section"
>
</general-confirmation-form-component>
</modal-component>
<div class="col-auto" v-if="!['customerGroupPaymentExpiredInvoiceComponent'].includes(section)">
<div class="btn bg-grey no-border" @click="expanded = !expanded">
<i class="fa" :class="{'fa-angle-down': !expanded, 'fa-angle-up': expanded}" ></i>
@@ -18,12 +18,18 @@
{{item.currency.short_code}} {{(Math.round((item.amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
</div>
</div>
<div class="col-auto p-l-0">
<div class="col-auto p-l-0" v-if="item.bill_no">
<div class="font-heading fs-8 muted all-caps">Bill Number</div>
<div class="font-heading fs-10 bold">
{{ item.bill_no }}
</div>
</div>
<div class="col-auto p-l-0" v-else-if="item.payment_transaction && $store.getters.isAdmin">
<div class="font-heading fs-8 muted all-caps">Bill Number</div>
<div class="font-heading fs-10 bold">
{{ item.payment_transaction.bill_no }}
</div>
</div>
</div>
</div>
</div>
@@ -80,7 +80,7 @@
</div>
<div class="row">
<div class="col">
<div class="font-heading all-caps fs-10 bold">Maybank: <span class="text-complete">562237009234</span></div>
<div class="font-heading all-caps fs-10 bold">Maybank: <span class="text-complete">568603010762</span></div>
</div>
</div>
<div class="row">
@@ -19,16 +19,16 @@
{{item.currency.short_code}} {{(Math.round((item.amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
</div>
</div>
<div class="col-auto p-l-0">
<div class="col-auto p-l-0" v-if="$store.getters.isAdmin">
<div class="font-heading fs-8 muted all-caps">Bill Number</div>
<div class="font-heading fs-10 bold">
{{ item.bill_no }}
{{ item.payment_transaction.bill_no }}
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="font-heading fs-8 all-caps" :class="[{'text-danger': item.payment_transaction.status === 4}, {'text-primary': item.payment_transaction.status !== 4}]">{{ item.payment_transaction.status === 2 ? 'Received' : item.payment_transaction.status === 4 ? 'Rejected' : 'Submitted'}} On: {{item.updated_at}}</div>
<div class="font-heading fs-8 all-caps" :class="[{'text-danger': item.payment_transaction.status === 4}, {'text-primary': item.payment_transaction.status !== 4}]">{{ item.payment_transaction.status === 2 ? 'Received' : item.payment_transaction.status === 4 ? 'Rejected' : 'Submitted'}} On: {{item.payment_transaction.updated_at}}</div>
</div>
</div>
</div>
@@ -81,12 +81,12 @@
</div>
<div class="row">
<div class="col">
<div class="font-heading all-caps fs-10 bold">Maybank: <span class="text-complete">562237009234</span></div>
<div class="font-heading all-caps fs-10 bold">Maybank: <span class="text-complete">568603010762</span></div>
</div>
</div>
<div class="row">
<div class="col">
<div class="font-heading all-caps fs-10 bold">Bank In Amount: <span class="text-success">{{(Math.round((parseFloat(amount) + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}} MYR</span></div>
<div class="font-heading all-caps fs-10 bold">Bank In Amount: <span class="text-success">{{(Math.round((parseFloat(item.amount) + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}} MYR</span></div>
</div>
</div>
</div>
@@ -115,7 +115,7 @@
</div>
<div class="row">
<div class="col">
<div class="font-heading all-caps fs-10 bold">Maybank: <span class="text-complete">562237009234</span></div>
<div class="font-heading all-caps fs-10 bold">Maybank: <span class="text-complete">568603010762</span></div>
</div>
</div>
<div class="row">
@@ -76,7 +76,7 @@
</div>
<div class="row">
<div class="col">
<div class="font-heading all-caps fs-10 bold">Maybank: <span class="text-complete">562237009234</span></div>
<div class="font-heading all-caps fs-10 bold">Maybank: <span class="text-complete">568603010762</span></div>
</div>
</div>
<div class="row">
@@ -29,7 +29,7 @@
</div>
<div class="row">
<div class="col">
<div class="font-heading all-caps">{{ data.model }}</div>
<div class="font-heading all-caps" :class="[{ 'text-danger': data.show_remind }]">{{ data.model }}</div>
</div>
</div>
</div>
@@ -41,7 +41,7 @@
</div>
<div class="row">
<div class="col">
<div class="font-heading all-caps">{{ data.expiry_date }}</div>
<div class="font-heading all-caps" :class="[{ 'text-danger': data.show_remind }]">{{ data.expiry_date }}</div>
</div>
</div>
</div>
@@ -53,7 +53,7 @@
</div>
<div class="row">
<div class="col">
<div class="font-heading all-caps">{{ data.reminder_date }}</div>
<div class="font-heading all-caps" :class="[{ 'text-danger': data.show_remind }]">{{ data.reminder_date }}</div>
</div>
</div>
</div>
@@ -65,7 +65,7 @@
</div>
<div class="row">
<div class="col">
<div class="font-heading all-caps">{{ data.created_at }}</div>
<div class="font-heading all-caps" :class="[{ 'text-danger': data.show_remind }]">{{ data.created_at }}</div>
</div>
</div>
</div>
@@ -1,4 +1,5 @@
@extends('layouts.base_portal')
@section('inner_content')
<container-profile-section-component :id="{{$id}}"></container-profile-section-component>
<!-- <container-profile-section-component :id="{{$id}}"></container-profile-section-component> -->
<container-profile-v2-section-component :id="{{$id}}"></container-profile-v2-section-component>
@endsection
+1 -1
View File
@@ -16,7 +16,7 @@
<tbody>
<tr align="center">
<td>
<img src="{{ url('https://chart.googleapis.com/chart?chs=250x250&cht=qr&chl={"id":'.$order->id.'}') }}" style="width: 230px; height: 230px;" />
<img src="{{ url(config('qr.qr_code_img_url') . '{id:'.$order->id.'}') }}" style="width: 230px; height: 230px;" />
</td>
</tr>
<tr align="center">
+1
View File
@@ -47,6 +47,7 @@ Route::group(['prefix' => 'transactions', 'namespace' => 'Transactions', 'as' =>
Route::get('/list', 'ListGroupsController@list')->name('list');
// Route::get('/list', 'ListGroupsController@list')->middleware('storage.invoice.check.bygroup')->name('list');
Route::delete('/{id}/delete', 'DeleteGroupController@delete')->name('delete');
Route::delete('/{id}/delete-paid', 'DeletePaidGroupController@delete')->name('paidGroup.delete');
Route::put('/{id}/update', 'UpdateGroupController@update')->name('update');
// Route::post('/{id}/approve', 'CreateBulkPurchaseOrderDocumentController@aprove')->name('approve');
// Route::post('/bulk/po', 'CreateBulkPurchaseOrderDocumentController@create')->name('bulk.po');
+43
View File
@@ -1253,3 +1253,46 @@ Route::get('fix-payment-status-updated-but-failed-update-invoice', function (Upd
Route::get('/payment-and-billing-2', function () {
return view('pages.paymentAndBilling2');
})->name('admin.payment-and-billing-2');
Route::get('/show-all-extra-payments', function () {
ini_set('memory_limit', '-1');
$invoices = Transaction::where('type', TransactionType::SHIPPING_INVOICE)
->where('status', ApprovalStatus::COMPLETED)
->whereHas('transactions', function ($query) {
$query->where('type', TransactionType::PAYMENT)
->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]);
})
->get();
echo '<table>
<tr>
<th>Transaction Type</th>
<th>Total</th>
<th>Paid</th>
<th>Customer</th>
<th>Order</th>
</tr>';
foreach ($invoices as $invoice) {
$paidAmount = $invoice->transactions()->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->sum('amount');
$packingList = $invoice->owner;
$order = $packingList->owner;
$companyModule= $order->companyModule;
$marking = $companyModule->getMarking();
if (($paidAmount <= $invoice->amount) || ($paidAmount - $invoice->amount < 0.01)) {
continue;
}
echo '<tr>';
echo '<td>' . $invoice->type . '</td>';
echo '<td>' . $invoice->amount . '</td>';
echo '<td>' . $paidAmount . '</td>';
echo '<td><a href="'.route('customer.profile', $marking).'" target="_blank">'.$marking.'</a></td>';
echo '<td><a target="_blank" href="' . route('order.show', $order->reference) . '">' . $order->reference . ' - ' . $order->created_at . '</a><br></td>';
echo '</tr>';
}
echo '</table>';
});