mirror of
https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal.git
synced 2026-08-19 12:34:18 +00:00
Compare commits
143 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bcfeb49275 | |||
| b4c6e721fd | |||
| aa65b333c8 | |||
| 656c50e047 | |||
| 275157b243 | |||
| 0c9ffd2bf7 | |||
| a953f78771 | |||
| cf3e7f04e4 | |||
| be0cd16285 | |||
| d4dcae155d | |||
| bad8cadb3a | |||
| 3af32cc6e7 | |||
| 34bab6a45c | |||
| dd1eae1ea2 | |||
| b46bfb38bf | |||
| 19c4ee4fda | |||
| 13f13c7a0e | |||
| ffa63f611b | |||
| 82675ab80c | |||
| aac04c4135 | |||
| 56dca799f8 | |||
| 42d8f811c6 | |||
| 030136fd03 | |||
| c8b6e271e3 | |||
| f93997b858 | |||
| 6fbc23d7c4 | |||
| e0a264d58f | |||
| fec20b0947 | |||
| 0bf61d93c5 | |||
| bea24fb48e | |||
| 17a4522f50 | |||
| dfedb99c13 | |||
| 669cac9bd4 | |||
| d7625aece7 | |||
| a36c5c3063 | |||
| 2f55821046 | |||
| 4a9ac3de02 | |||
| 1e6fafef28 | |||
| fd75da5778 | |||
| b593605c72 | |||
| 8d75012390 | |||
| 2d98757c1c | |||
| b329f232f2 | |||
| 713922d2ee | |||
| 74d11f8305 | |||
| ea920717a1 | |||
| e1b49f6be0 | |||
| 1be405ca93 | |||
| 9d0924c674 | |||
| e63e3e707f | |||
| aeaec32dcb | |||
| b000c25e66 | |||
| 1e9af59b91 | |||
| a392b8a5eb | |||
| 30edc3eaba | |||
| b0eca18343 | |||
| 88e1b43f19 | |||
| fc9f6d6dde | |||
| 141dab15b6 | |||
| c9ac435e37 | |||
| 6d01bdfb60 | |||
| e2dc83e441 | |||
| e9daadaf60 | |||
| 7cace7e800 | |||
| 64fa56c02f | |||
| 3f962e774d | |||
| 4ba2144f02 | |||
| 69f2b384cf | |||
| f1a35299e6 | |||
| b15866ea16 | |||
| bd42f7213a | |||
| 2d92b1a8ab | |||
| 06e3049e50 | |||
| b0fa73a12b | |||
| 5d66761465 | |||
| 1ac4615c99 | |||
| 590960b5fd | |||
| 5f24f58480 | |||
| 4dec576aa0 | |||
| 4a41c89024 | |||
| a0997a4649 | |||
| b90dae882e | |||
| f361a7e185 | |||
| 29619625d1 | |||
| 1705b5c2e5 | |||
| 1813783d87 | |||
| 46a0e670ba | |||
| dcec8cb33b | |||
| 75037f6192 | |||
| 675324081b | |||
| a959e83f5b | |||
| 2802e3c366 | |||
| aac2a0666a | |||
| 19efba4b89 | |||
| 7d70c800db | |||
| 863dc94dad | |||
| 98e45e27e3 | |||
| df2916594b | |||
| a49920973e | |||
| d129f8f6bd | |||
| 55a82e52a4 | |||
| 1d4ac80b8f | |||
| 7cd376a9b5 | |||
| c7e3091f9b | |||
| 28feba2ae9 | |||
| 6176135f85 | |||
| 5f529965da | |||
| 924f4f2ace | |||
| 6369282b38 | |||
| 1991cf2c57 | |||
| 5f5bbe0c8c | |||
| a809aec9a7 | |||
| 68ce8373e9 | |||
| e5347f56b7 | |||
| 6673a44137 | |||
| 4d3345f613 | |||
| 60b8657773 | |||
| 9f7a8d0d4b | |||
| a87ab6c27f | |||
| 462a4776cd | |||
| 7e029c5610 | |||
| 0719285286 | |||
| 64400d1524 | |||
| be0279f56b | |||
| e15170bc7f | |||
| 59f527aee7 | |||
| d7aa248972 | |||
| 1679d1ecf4 | |||
| 7ca48e9638 | |||
| 14278a888a | |||
| 5de2554d63 | |||
| 033a835fce | |||
| 66ddb5da23 | |||
| f95545a985 | |||
| 9e8685bd02 | |||
| 1224735ba8 | |||
| 11e2390059 | |||
| c280da36d7 | |||
| f1b8c6a556 | |||
| 6d210d3713 | |||
| 5dd2df02fd | |||
| b207b11336 | |||
| ffd95ee1cc |
@@ -59,3 +59,7 @@ YD_API_CODE=''
|
||||
PERFEXCRM_BASE_URL=""
|
||||
PERFEXCRM_API_KEY=""
|
||||
PERFEXCRM_IS_ENABLED="false"
|
||||
|
||||
|
||||
STORAGE_FEE_LAUNCH_DATE="2023-12-11 00:00:00"
|
||||
SST_START_DATE="2024-04-01 00:00:00"
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\General\Eloquent\Filters;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class CompanySegmentsIn implements Filter
|
||||
{
|
||||
/**
|
||||
* @param Builder $builder
|
||||
* @param $value
|
||||
* @return mixed
|
||||
*/
|
||||
public static function apply(Builder $builder, $value)
|
||||
{
|
||||
return $builder->whereHas('companyModules', function ($module) use ($value) {
|
||||
$module->whereHas('connections', function ($connection) use ($value) {
|
||||
$connection->whereHas('connectionSegments', function ($segment) use ($value) {
|
||||
$segment->whereIn('segment_id', $value);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class FetchOrdersFromYDPortalJob implements ShouldQueue
|
||||
{
|
||||
@@ -29,12 +30,17 @@ class FetchOrdersFromYDPortalJob implements ShouldQueue
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
Log::info('FetchOrdersFromYDPortalJob starts');
|
||||
Log::info('FetchPackingListsFromYdPortalProcessor starts');
|
||||
(App()->make(FetchPackingListsFromYdPortalProcessor::class))->execute();
|
||||
Log::info('FetchContainersFromYdPortalProcessor starts');
|
||||
(App()->make(FetchContainersFromYdPortalProcessor::class))->execute();
|
||||
Log::info('FetchContainersUpdatesFromYdPortalProcessor starts');
|
||||
(App()->make(FetchContainersUpdatesFromYdPortalProcessor::class))->execute();
|
||||
Log::info('FetchDeliveryUpdatesFromYdPortalProcessor starts');
|
||||
(App()->make(FetchDeliveryUpdatesFromYdPortalProcessor::class))->execute();
|
||||
|
||||
// (App()->make(FetchOrderListsFromYdPortalProcessor::class))->execute();
|
||||
Log::info('FetchOrdersFromYDPortalJob ends');
|
||||
// (App()->make(FetchOrderListsFromYdPortalProcessor::class))->execute();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -36,6 +36,8 @@ use App\Models\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class CreateCustomerLogic extends AbstractControllerLogic
|
||||
{
|
||||
@@ -167,6 +169,18 @@ class CreateCustomerLogic extends AbstractControllerLogic
|
||||
CreatePerfexCRMCustomer::dispatch($createLeadPerfexCRMObject);
|
||||
}
|
||||
|
||||
if(!app()->environment(['production'])){
|
||||
// call wac webhook
|
||||
$url = 'https://wacontact.readyspace.com/rest/trigger/9fe03daf-2ace-4095-b064-601ef6d9bfe7';
|
||||
$payload = [
|
||||
'name' => $request->input('name'),
|
||||
'email' => $request->input('email'),
|
||||
'phone' => $request->input('phone'),
|
||||
];
|
||||
$response = Http::post($url, $payload);
|
||||
Log::channel('wac_webhook')->info(json_encode($response));
|
||||
}
|
||||
|
||||
// $this->generateEmailVerificationAttemptProcessor->execute($user);
|
||||
|
||||
return $this->response($this->authenticationProcessor->execute($request));
|
||||
|
||||
@@ -15,6 +15,7 @@ use App\Classes\Modules\Contacts\Processors\CreateContactProcessor;
|
||||
use App\Classes\Modules\Remarks\DataTransferObjects\RemarkObject;
|
||||
use App\Classes\Modules\Remarks\Processors\CreateRemarkProcessor;
|
||||
use App\Classes\ValueObjects\Constants\ApprovalStatus;
|
||||
use App\Classes\ValueObjects\Constants\RemarkTypes;
|
||||
use App\Http\Resources\AddressResource;
|
||||
use App\Models\Address;
|
||||
use ErrorException;
|
||||
@@ -100,6 +101,16 @@ class CreateAddressLogic extends AbstractControllerLogic
|
||||
$this->createRemarkProcessor->execute($address, $remarkObject);
|
||||
}
|
||||
|
||||
$addressExtraFields = [
|
||||
'property_type' => $request->input('property_type'),
|
||||
'tools_required_unload' => $request->input('tools_required_unload'),
|
||||
'pickup_time_from' => $request->input('pickup_time_from'),
|
||||
'pickup_time_to' => $request->input('pickup_time_to'),
|
||||
];
|
||||
|
||||
$addressExtraFieldsObject = new RemarkObject(json_encode($addressExtraFields), Auth()->user()->id, RemarkTypes::ADDRESS_EXTRA_COLUMNS);
|
||||
$this->createRemarkProcessor->execute($address, $addressExtraFieldsObject);
|
||||
|
||||
return $this->resourceResponse(new AddressResource($address));
|
||||
|
||||
}
|
||||
|
||||
@@ -15,10 +15,12 @@ use App\Classes\Modules\Remarks\DataTransferObjects\RemarkObject;
|
||||
use App\Classes\Modules\Remarks\Processors\CreateRemarkProcessor;
|
||||
use App\Classes\ValueObjects\Constants\AddressType;
|
||||
use App\Classes\ValueObjects\Constants\ApprovalStatus;
|
||||
use App\Classes\ValueObjects\Constants\RemarkTypes;
|
||||
use App\Http\Resources\AddressResource;
|
||||
use App\Models\Address;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class UpdateAddressLogic extends AbstractControllerLogic
|
||||
{
|
||||
@@ -102,6 +104,25 @@ class UpdateAddressLogic extends AbstractControllerLogic
|
||||
$this->createRemarkProcessor->execute($address, $remarkObject);
|
||||
}
|
||||
|
||||
if ($request->input('pickup_time_to') <= $request->input('pickup_time_from')) {
|
||||
$pickupTimeFrom = Carbon::parse($request->input('pickup_time_from'));
|
||||
$request->merge([
|
||||
'pickup_time_to' => $pickupTimeFrom->addHour()->format('H:i') // Format to hh:mm
|
||||
]);
|
||||
}
|
||||
|
||||
$addressExtraFields = [
|
||||
'property_type' => $request->input('property_type'),
|
||||
'additional_request' => $request->input('additional_request'),
|
||||
'receive_goods_working_hours' => $request->input('receive_goods_working_hours'),
|
||||
'receive_goods_after_hours' => $request->input('receive_goods_after_hours'),
|
||||
'receive_goods_on_saturday' => $request->input('receive_goods_on_saturday'),
|
||||
];
|
||||
|
||||
$address->addressExtraFields()->delete();
|
||||
$addressExtraFieldsObject = new RemarkObject(json_encode($addressExtraFields), Auth()->user()->id, RemarkTypes::ADDRESS_EXTRA_COLUMNS);
|
||||
$this->createRemarkProcessor->execute($address, $addressExtraFieldsObject);
|
||||
|
||||
return $this->resourceResponse(new AddressResource($address));
|
||||
|
||||
}
|
||||
|
||||
@@ -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){
|
||||
|
||||
+13
-1
@@ -7,6 +7,8 @@ use App\Classes\General\Abstracts\AbstractControllerLogic;
|
||||
use App\Classes\Modules\Companies\Processors\AssignConnectionSegmentProcessor;
|
||||
use App\Classes\Modules\Companies\Services\FetchesCompany;
|
||||
use App\Classes\Modules\Companies\Services\FetchesCompanyConnection;
|
||||
use App\Classes\Modules\Contacts\DataTransferObjects\ContactObject;
|
||||
use App\Classes\Modules\Contacts\Processors\CreateContactProcessor;
|
||||
use App\Http\Resources\CompanyResource;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -33,17 +35,22 @@ class AssignCompanyConnectionToConnectionSegmentLogic extends AbstractController
|
||||
/** @var AssignConnectionSegmentProcessor */
|
||||
private $assignCompanyConnectionToConnectionSegmentProcessor;
|
||||
|
||||
/** @var CreateContactProcessor */
|
||||
private $createContactProcessor;
|
||||
|
||||
/**
|
||||
* AssignCompanyToSegmentLogic constructor.
|
||||
* @param FetchesCompany $fetchesCompany
|
||||
* @param FetchesCompanyConnection $fetchesCompanyConnection
|
||||
* @param AssignConnectionSegmentProcessor $assignCompanyConnectionToConnectionSegmentProcessor
|
||||
* @param CreateContactProcessor $createContactProcessor
|
||||
*/
|
||||
public function __construct(FetchesCompany $fetchesCompany, FetchesCompanyConnection $fetchesCompanyConnection, AssignConnectionSegmentProcessor $assignCompanyConnectionToConnectionSegmentProcessor)
|
||||
public function __construct(FetchesCompany $fetchesCompany, FetchesCompanyConnection $fetchesCompanyConnection, AssignConnectionSegmentProcessor $assignCompanyConnectionToConnectionSegmentProcessor, CreateContactProcessor $createContactProcessor)
|
||||
{
|
||||
$this->fetchesCompany = $fetchesCompany;
|
||||
$this->fetchesCompanyConnection = $fetchesCompanyConnection;
|
||||
$this->assignCompanyConnectionToConnectionSegmentProcessor = $assignCompanyConnectionToConnectionSegmentProcessor;
|
||||
$this->createContactProcessor = $createContactProcessor;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,6 +69,11 @@ class AssignCompanyConnectionToConnectionSegmentLogic extends AbstractController
|
||||
|
||||
$this->assignCompanyConnectionToConnectionSegmentProcessor->execute($companyConnection, $request->input('segment_id'));
|
||||
|
||||
if ($request->input('segment_id') == 10 || $request->input('segment_id') == 11) {
|
||||
$contactObject = new ContactObject('Whatsapp: ' . $request->input('name'), $request->input('phone'), null, null);
|
||||
$this->createContactProcessor->execute($contactObject, $company);
|
||||
}
|
||||
|
||||
return $this->resourceResponse(new CompanyResource($company));
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -31,6 +31,7 @@ class ExportsPaymentTransactions implements FromQuery, WithHeadings, WithHeading
|
||||
return [
|
||||
'DocNo',
|
||||
'DocDate',
|
||||
'PaymentDate',
|
||||
'DebtorCode',
|
||||
'Ref',
|
||||
'ShipInfo',
|
||||
@@ -41,6 +42,9 @@ class ExportsPaymentTransactions implements FromQuery, WithHeadings, WithHeading
|
||||
'DeptNo',
|
||||
'Qty',
|
||||
'UnitPrice',
|
||||
'TaxType',
|
||||
'TaxableAmt',
|
||||
'TaxRate',
|
||||
// 'marking',
|
||||
// 'contact person',
|
||||
// 'contact number',
|
||||
@@ -56,12 +60,12 @@ class ExportsPaymentTransactions implements FromQuery, WithHeadings, WithHeading
|
||||
{
|
||||
$start_date = $this->request->input('startDate', null);
|
||||
if ($start_date) {
|
||||
$start_date = Carbon::parse($this->request->input('startDate'))->format('Y-m-d');
|
||||
$start_date = Carbon::parse($start_date)->startOfDay();
|
||||
}
|
||||
|
||||
$end_date = $this->request->input('endDate', null);
|
||||
if ($end_date) {
|
||||
$end_date = Carbon::parse($this->request->input('endDate'))->format('Y-m-d');
|
||||
$end_date = Carbon::parse($end_date)->endOfDay();
|
||||
}
|
||||
|
||||
$query = Transaction::query();
|
||||
@@ -74,30 +78,31 @@ class ExportsPaymentTransactions implements FromQuery, WithHeadings, WithHeading
|
||||
$approvalStatus = ApprovalStatus::APPROVED;
|
||||
}
|
||||
|
||||
// $query->where('type', TransactionType::SHIPPING_INVOICE)->whereIn('status', [$approvalStatus]);
|
||||
$query->whereIn('type', [TransactionType::SHIPPING_INVOICE, TransactionType::STORAGE_INVOICE])->whereIn('status', [$approvalStatus]);
|
||||
// Adjusted the query to include both types and status
|
||||
$query->whereIn('type', [TransactionType::SHIPPING_INVOICE, TransactionType::STORAGE_INVOICE])
|
||||
->where('status', $approvalStatus);
|
||||
|
||||
if($start_date && $end_date) {
|
||||
$query->whereBetween('updated_at', [
|
||||
Carbon::parse($start_date)->format('Y-m-d 0:00:00'),
|
||||
Carbon::parse($end_date)->format('Y-m-d 23:59:59')
|
||||
]);
|
||||
}
|
||||
elseif($start_date && !$end_date) {
|
||||
$query->whereHas('transactions', function($transaction) use ($start_date) {
|
||||
$transaction->where('type', TransactionType::PAYMENT)->where('updated_at', '>=', Carbon::parse($start_date)->format('Y-m-d 0:00:00'));
|
||||
if ($start_date && $end_date) {
|
||||
$query->whereHas('transactions', function($transaction) use ($start_date, $end_date) {
|
||||
$transaction->where('type', TransactionType::PAYMENT)
|
||||
->whereBetween('updated_at', [$start_date, $end_date]);
|
||||
});
|
||||
|
||||
}
|
||||
elseif(!$start_date && $end_date) {
|
||||
} elseif ($start_date) {
|
||||
$query->whereHas('transactions', function($transaction) use ($start_date) {
|
||||
$transaction->where('type', TransactionType::PAYMENT)
|
||||
->where('updated_at', '>=', $start_date);
|
||||
});
|
||||
} elseif ($end_date) {
|
||||
$query->whereHas('transactions', function($transaction) use ($end_date) {
|
||||
$transaction->where('type', TransactionType::PAYMENT)->where('updated_at', '>=', Carbon::parse($end_date)->format('Y-m-d 0:00:00'));
|
||||
$transaction->where('type', TransactionType::PAYMENT)
|
||||
->where('updated_at', '<=', $end_date);
|
||||
});
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
|
||||
public function map($transaction): array
|
||||
{
|
||||
$container = $transaction->owner->containers()->first();
|
||||
@@ -130,9 +135,41 @@ class ExportsPaymentTransactions implements FromQuery, WithHeadings, WithHeading
|
||||
$furtherDescription .= $item->name.' '.$item->quantity.' X '.$item->price."\n";
|
||||
}
|
||||
|
||||
$transactionDetails = $transaction->transactionDetails;
|
||||
|
||||
$firstItem = true;
|
||||
$rows = [];
|
||||
foreach ($transactionDetails as $detail) {
|
||||
// Prepare each row based on the transaction detail
|
||||
$rows[] = [
|
||||
$firstItem ? '<<New>>' : '',
|
||||
$transaction->created_at->format('m/d/Y H:m'),
|
||||
$transaction->transactions()->where('type', TransactionType::PAYMENT)->first()->updated_at->format('m/d/Y H:m'),
|
||||
$company->debtor,
|
||||
$order->reference,
|
||||
$order->reference,
|
||||
'500-0000',
|
||||
str_replace('<br>', ' ', $detail->name),
|
||||
'',
|
||||
$container->reference,
|
||||
'CIEF',
|
||||
$detail->quantity,
|
||||
$detail->price,
|
||||
floatval($detail->tax_percentage) > 0 ? 'SV-6' : '',
|
||||
floatval($detail->tax_percentage) > 0 ? $detail->amount : '0',
|
||||
$detail->tax_percentage,
|
||||
];
|
||||
|
||||
if($firstItem) {
|
||||
$firstItem = false;
|
||||
}
|
||||
}
|
||||
|
||||
return $rows;
|
||||
|
||||
return [
|
||||
'<<New>>',
|
||||
$transaction->created_at->format('m/d/Y H:m'),
|
||||
$transaction->transactions()->where('type', TransactionType::PAYMENT)->first()->updated_at->format('m/d/Y H:m'),
|
||||
$company->debtor,
|
||||
$order->reference,
|
||||
$order->reference,
|
||||
|
||||
+11
-17
@@ -56,27 +56,21 @@ class RescheduleContainerLogic extends AbstractControllerLogic
|
||||
*/
|
||||
public function logic(Request $request) : JsonResponse
|
||||
{
|
||||
try {
|
||||
$container = $this->fetchesContainer->execute(['id' => $request->route('id')]);
|
||||
$transport = $container->transports()->first();
|
||||
$container = $this->fetchesContainer->execute(['id' => $request->route('id')]);
|
||||
$transport = $container->transports()->first();
|
||||
|
||||
$old_sechedule = $transport->schedules()->first();
|
||||
$old_schedule = $transport->schedules()->delete();
|
||||
|
||||
$this->updatesScheduleStatus->execute($old_sechedule, ApprovalStatus::REJECTED);
|
||||
// $this->updatesScheduleStatus->execute($old_schedule, ApprovalStatus::REJECTED);
|
||||
|
||||
$scheduleObject = new ScheduleObject(
|
||||
Carbon::parse($request->input('etd')),
|
||||
Carbon::parse($request->input('eta')),
|
||||
ApprovalStatus::APPROVED
|
||||
);
|
||||
$schedule = $this->createsSchedule->execute($transport, $scheduleObject);
|
||||
|
||||
return $this->resourceResponse(new ContainerResource($container));
|
||||
|
||||
} catch (\Exception $exception){
|
||||
throw new ErrorException($exception->getMessage(), $exception->getCode());
|
||||
}
|
||||
$scheduleObject = new ScheduleObject(
|
||||
Carbon::parse($request->input('etd')),
|
||||
Carbon::parse($request->input('eta')),
|
||||
ApprovalStatus::APPROVED
|
||||
);
|
||||
$schedule = $this->createsSchedule->execute($transport, $scheduleObject);
|
||||
|
||||
return $this->resourceResponse(new ContainerResource($container));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-1
@@ -76,6 +76,7 @@ class FetchDeliveryUpdatesFromYdPortalProcessor
|
||||
try {
|
||||
$client = new \GuzzleHttp\Client(['cookies' => true, 'headers' => ['Cookie' => 'utc_offset=480']]);
|
||||
|
||||
Log::info('Delivery tracking sTrackingNo: '. $packingList->reference);
|
||||
$request = $client->request('get', 'https://main.universe.com.my/Tracking/User/Paging?sEcho=1&sTrackingNo='.$packingList->reference.'&sOrgId=sti', ['timeout' => 3]);
|
||||
$deliveryTracking = json_decode($request->getBody()->getContents());
|
||||
foreach (array_reverse($deliveryTracking->aaData) as $trackingRow) {
|
||||
@@ -119,7 +120,7 @@ class FetchDeliveryUpdatesFromYdPortalProcessor
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Log::info('FetchDeliveryUpdatesFromYdPortalProcessor ends');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+7
-1
@@ -138,7 +138,13 @@ class FetchPackingListsFromYdPortalProcessor
|
||||
|
||||
$receiveDate = Carbon::parse(substr(preg_replace("/[^0-9]/", "", $row->expressno), 0, 8));
|
||||
|
||||
$customerno = preg_split('(-|\(|\)|\/)', $row->customerno);
|
||||
$customerno = $row->customerno;
|
||||
// Check if $customerno contains '正确唛头YD' and extract the part after it
|
||||
if (strpos($customerno, '正确唛头YD') !== false) {
|
||||
$customerno = explode('正确唛头YD', $customerno)[1];
|
||||
}
|
||||
|
||||
$customerno = preg_split('/[-()\/]/', $customerno);
|
||||
|
||||
$orderNumber = $customerno[array_key_last($customerno)];
|
||||
$allow_contract = true;
|
||||
|
||||
@@ -13,10 +13,14 @@ class RemarkObject implements DataTransferObject
|
||||
/** @var string*/
|
||||
private $content;
|
||||
|
||||
public function __construct(string $content, int $commenterID)
|
||||
/** @var int|null */
|
||||
private $type;
|
||||
|
||||
public function __construct(string $content, int $commenterID, int $type = null)
|
||||
{
|
||||
$this->commenterID = $commenterID;
|
||||
$this->content = $content;
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -35,4 +39,12 @@ class RemarkObject implements DataTransferObject
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null
|
||||
*/
|
||||
public function getType(): ?int
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ class CreatesRemark extends AbstractUpdateRelationshipRecord
|
||||
|
||||
$model->commenter_id = $object->getCommenterId();
|
||||
$model->content = $object->getContent();
|
||||
$model->type = $object->getType();
|
||||
|
||||
return $this->handler($remarkable->remarks(), $model);
|
||||
|
||||
|
||||
@@ -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([]);
|
||||
}
|
||||
}
|
||||
+24
-3
@@ -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([]);
|
||||
}
|
||||
|
||||
+15
-7
@@ -15,6 +15,7 @@ use Mccarlosen\LaravelMpdf\Facades\LaravelMpdf;
|
||||
use App\Classes\Modules\Documents\Services\CreatesDocument;
|
||||
use App\Classes\Modules\Documents\Services\CreatesFiles;
|
||||
use App\Models\Document;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class RegenerateShippingInvoiceTransactionLogic extends AbstractControllerLogic
|
||||
{
|
||||
@@ -51,11 +52,18 @@ class RegenerateShippingInvoiceTransactionLogic extends AbstractControllerLogic
|
||||
foreach ($orders as $order){
|
||||
$invoices = $order->transactions()->where('transactions.type', TransactionType::SHIPPING_INVOICE)->get();
|
||||
foreach ($invoices as $invoice){
|
||||
|
||||
|
||||
$invoice->documents()->delete();
|
||||
|
||||
$transaction_invoice_pdf = LaravelMpdf::loadView('pages.pdfs.shipping_invoice', ['invoice_transaction' => $invoice]);
|
||||
|
||||
|
||||
$view = 'pages.pdfs.shipping_invoice';
|
||||
$dateToCompare = Carbon::parse(env('SST_START_DATE', '2024-04-01 00:00:00'));
|
||||
$shippingInvoiceTransactionCreatedDate = Carbon::parse($invoice->created_at);
|
||||
if ($shippingInvoiceTransactionCreatedDate->isAfter($dateToCompare) && $invoice->tax > 0) {
|
||||
$view = 'pages.pdfs.shipping_invoice_sst';
|
||||
}
|
||||
|
||||
$transaction_invoice_pdf = LaravelMpdf::loadView($view, ['invoice_transaction' => $invoice]);
|
||||
|
||||
$document_object = new DocumentObject(
|
||||
DocumentType::SHIPPING_INVOICE,
|
||||
[chunk_split('data:application/pdf;base64,'.base64_encode($transaction_invoice_pdf->output()))],
|
||||
@@ -63,11 +71,11 @@ class RegenerateShippingInvoiceTransactionLogic extends AbstractControllerLogic
|
||||
ApprovalStatus::COMPLETED,
|
||||
'shipping_invoice'
|
||||
);
|
||||
|
||||
|
||||
$document =$this->createsDocument->execute($invoice, $document_object);
|
||||
|
||||
|
||||
$this->createsFiles->execute($document, $document_object);
|
||||
|
||||
|
||||
// dump($document);
|
||||
}
|
||||
}
|
||||
|
||||
+9
-1
@@ -16,6 +16,7 @@ use App\Classes\Modules\Documents\Services\CreatesDocument;
|
||||
use App\Classes\Modules\Documents\Services\CreatesFiles;
|
||||
use App\Classes\Modules\Transactions\Services\FetchesTransaction;
|
||||
use App\Models\Document;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class RegenerateSingleShippingInvoiceTransactionLogic extends AbstractControllerLogic
|
||||
{
|
||||
@@ -54,7 +55,14 @@ class RegenerateSingleShippingInvoiceTransactionLogic extends AbstractController
|
||||
|
||||
$invoice->documents()->delete();
|
||||
|
||||
$transaction_invoice_pdf = LaravelMpdf::loadView('pages.pdfs.shipping_invoice', ['invoice_transaction' => $invoice]);
|
||||
$view = 'pages.pdfs.shipping_invoice';
|
||||
$dateToCompare = Carbon::parse(env('SST_START_DATE', '2024-04-01 00:00:00'));
|
||||
$shippingInvoiceTransactionCreatedDate = Carbon::parse($invoice->created_at);
|
||||
if ($shippingInvoiceTransactionCreatedDate->isAfter($dateToCompare) && $invoice->tax > 0) {
|
||||
$view = 'pages.pdfs.shipping_invoice_sst';
|
||||
}
|
||||
|
||||
$transaction_invoice_pdf = LaravelMpdf::loadView($view, ['invoice_transaction' => $invoice]);
|
||||
|
||||
$document_object = new DocumentObject(
|
||||
DocumentType::SHIPPING_INVOICE,
|
||||
|
||||
+28
-12
@@ -25,6 +25,8 @@ use App\Classes\Modules\Transactions\Services\DeletesTransactionDetails;
|
||||
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject;
|
||||
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionDetailObject;
|
||||
use App\Classes\Modules\Transactions\Services\FetchesTransaction;
|
||||
use App\Classes\ValueObjects\Constants\TaxPercentage;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class UpdateShippingInvoiceTransactionLogic extends AbstractControllerLogic
|
||||
{
|
||||
@@ -60,9 +62,9 @@ class UpdateShippingInvoiceTransactionLogic extends AbstractControllerLogic
|
||||
|
||||
/** @var DeletesTransactionDetails */
|
||||
private $deletesTransactionDetails;
|
||||
|
||||
|
||||
public function __construct(
|
||||
FetchesPackingList $fetchesPackingList,
|
||||
FetchesPackingList $fetchesPackingList,
|
||||
FetchesTransaction $fetchesTransaction,
|
||||
UpdatesTransaction $updatesTransaction,
|
||||
FetchesTransactionDetail $fetchesTransactionDetail,
|
||||
@@ -105,11 +107,25 @@ class UpdateShippingInvoiceTransactionLogic extends AbstractControllerLogic
|
||||
$transaction_detail = (object) $transaction_detail;
|
||||
|
||||
if(!in_array($transaction_detail->reference, ['SHIPPING_FEE', 'OVER_WEIGHT_CHARGES', 'MIN_CBM_CHARGES'])){
|
||||
$reference = 'CUSTOM_CHARGES';
|
||||
$taxPercentage = TaxPercentage::DEFAULT;
|
||||
|
||||
$dateToCompare = Carbon::parse(env('SST_START_DATE', '2024-04-01 00:00:00'));
|
||||
$shippingInvoiceTransactionCreatedDate = Carbon::parse($invoice_transaction->created_at);
|
||||
if ($shippingInvoiceTransactionCreatedDate->isAfter($dateToCompare)) {
|
||||
$taxPercentage = TaxPercentage::SIX_PERCENT;
|
||||
}
|
||||
|
||||
if($transaction_detail->reference === "PAY_ON_BEHALF"){
|
||||
$reference = "PAY_ON_BEHALF";
|
||||
$taxPercentage = TaxPercentage::NO_TAX;
|
||||
}
|
||||
$object_detail = new TransactionDetailObject(
|
||||
'CUSTOM_CHARGES',
|
||||
$reference,
|
||||
isset($transaction_detail->name) ? $transaction_detail->name : TransactionDetailType::CUSTOM_CHARGES,
|
||||
$transaction_detail->quantity,
|
||||
$transaction_detail->price
|
||||
$transaction_detail->price,
|
||||
$taxPercentage
|
||||
);
|
||||
|
||||
if(isset($transaction_detail->id)){
|
||||
@@ -121,20 +137,20 @@ class UpdateShippingInvoiceTransactionLogic extends AbstractControllerLogic
|
||||
}
|
||||
|
||||
$object = new TransactionObject(
|
||||
$invoice_transaction->bill_no,
|
||||
TransactionType::SHIPPING_INVOICE,
|
||||
1,
|
||||
$invoice_transaction->bill_no,
|
||||
TransactionType::SHIPPING_INVOICE,
|
||||
1,
|
||||
$invoice_transaction->issuer,
|
||||
1,
|
||||
1,
|
||||
PaymentMethodType::CASH,
|
||||
$invoice_transaction->transactionDetails()->sum('amount'),
|
||||
$invoice_transaction->transactionDetails()->sum('amount'),
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
null,
|
||||
$invoice_transaction->transactionDetails()->sum('tax_amount'),
|
||||
0,
|
||||
null,
|
||||
ApprovalStatus::PENDING_VERIFICATION
|
||||
);
|
||||
|
||||
|
||||
@@ -18,19 +18,25 @@ class TransactionDetailObject implements DataTransferObject
|
||||
/** @var float|null */
|
||||
private $price;
|
||||
|
||||
/** @var float|null */
|
||||
private $taxPercentage;
|
||||
|
||||
|
||||
/**
|
||||
* TransactionDetailObject constructor.
|
||||
* @param string $reference
|
||||
* @param string $name
|
||||
* @param float $quantity
|
||||
* @param float $price
|
||||
* @param float $taxPercentage
|
||||
*/
|
||||
public function __construct(?string $reference, ?string $name , ?float $quantity, ?float $price)
|
||||
public function __construct(?string $reference, ?string $name , ?float $quantity, ?float $price, ?float $taxPercentage)
|
||||
{
|
||||
$this->reference = $reference;
|
||||
$this->name = $name;
|
||||
$this->quantity = $quantity;
|
||||
$this->price = $price;
|
||||
$this->taxPercentage = $taxPercentage;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,9 +71,28 @@ class TransactionDetailObject implements DataTransferObject
|
||||
return $this->price;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function getAmount(): float
|
||||
{
|
||||
return $this->getQuantity() * $this->getPrice();
|
||||
return ($this->getQuantity() * $this->getPrice()) + $this->getTaxAmount();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function getTaxPercentage(): ?float
|
||||
{
|
||||
return $this->taxPercentage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function getTaxAmount(): float
|
||||
{
|
||||
return ($this->getQuantity() * $this->getPrice()) * $this->getTaxPercentage() / 100;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -80,21 +80,21 @@ class TransactionObject implements DataTransferObject
|
||||
* @param array|null $details
|
||||
*/
|
||||
public function __construct(
|
||||
string $billNo,
|
||||
string $transactionType,
|
||||
int $issuer,
|
||||
int $receiver,
|
||||
int $recipientBankAccountId,
|
||||
int $paymentMethod,
|
||||
float $amount,
|
||||
float $originalAmount,
|
||||
string $billNo,
|
||||
string $transactionType,
|
||||
int $issuer,
|
||||
int $receiver,
|
||||
int $recipientBankAccountId,
|
||||
int $paymentMethod,
|
||||
float $amount,
|
||||
float $originalAmount,
|
||||
int $currencyId,
|
||||
int $originalCurrencyId,
|
||||
int $originalCurrencyId,
|
||||
float $currencyRate,
|
||||
float $tax,
|
||||
float $serviceCharge,
|
||||
?Carbon $expiresOn,
|
||||
?int $status = ApprovalStatus::PENDING_SUBMISSION,
|
||||
float $tax,
|
||||
float $serviceCharge,
|
||||
?Carbon $expiresOn,
|
||||
?int $status = ApprovalStatus::PENDING_SUBMISSION,
|
||||
?array $details = [],
|
||||
?string $paymentReference = null
|
||||
)
|
||||
@@ -241,10 +241,10 @@ class TransactionObject implements DataTransferObject
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getDetails(): array
|
||||
public function getDetails(): array //cief todo: not in used as of 20240407
|
||||
{
|
||||
return array_map(function($product){
|
||||
return new TransactionDetailObject($product['stockCode'] ?? '', $product['description'] ?? '', $product['quantity'] ?? '', floatval(str_replace(',', '', $product['unit_price'])));
|
||||
return new TransactionDetailObject($product['stockCode'] ?? '', $product['description'] ?? '', $product['quantity'] ?? '', floatval(str_replace(',', '', $product['unit_price'])), 0.0 );
|
||||
}, $this->details);
|
||||
}
|
||||
|
||||
@@ -255,4 +255,4 @@ class TransactionObject implements DataTransferObject
|
||||
{
|
||||
return $this->paymentReference;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
-1
@@ -19,6 +19,7 @@ use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
|
||||
use App\Classes\Jobs\CreatePerfexCRMInvoice;
|
||||
use App\Classes\Modules\Transactions\Processors\CheckStorageInvoiceTransactionProcessor;
|
||||
use App\Models\Order;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class ApproveShippingInvoiceTransactionProcessor
|
||||
{
|
||||
@@ -59,9 +60,16 @@ class ApproveShippingInvoiceTransactionProcessor
|
||||
/** @var Transaction $invoice_transaction */
|
||||
$invoice_transaction = $packingList->transactions()->where('transactions.type', TransactionType::SHIPPING_INVOICE)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::PENDING_SUBMISSION])->first();
|
||||
|
||||
$view = 'pages.pdfs.shipping_invoice';
|
||||
$dateToCompare = Carbon::parse(env('SST_START_DATE', '2024-04-01 00:00:00'));
|
||||
$shippingInvoiceTransactionCreatedDate = Carbon::parse($invoice_transaction->created_at);
|
||||
if ($shippingInvoiceTransactionCreatedDate->isAfter($dateToCompare) && $invoice_transaction->tax > 0) {
|
||||
$view = 'pages.pdfs.shipping_invoice_sst';
|
||||
}
|
||||
|
||||
$this->updatesTransactionStatus->execute($invoice_transaction, ApprovalStatus::APPROVED);
|
||||
|
||||
$transaction_invoice_pdf = LaravelMpdf::loadView('pages.pdfs.shipping_invoice', ['invoice_transaction' => $invoice_transaction]);
|
||||
$transaction_invoice_pdf = LaravelMpdf::loadView($view, ['invoice_transaction' => $invoice_transaction]);
|
||||
|
||||
$document_object = new DocumentObject(
|
||||
DocumentType::SHIPPING_INVOICE,
|
||||
|
||||
+46
-21
@@ -23,6 +23,7 @@ use App\Classes\ValueObjects\Constants\PaymentMethodType;
|
||||
use App\Classes\ValueObjects\Constants\ApprovalStatus;
|
||||
use App\Classes\ValueObjects\Constants\PackageType;
|
||||
use App\Classes\ValueObjects\Constants\PackingListType;
|
||||
use App\Classes\ValueObjects\Constants\TaxPercentage;
|
||||
use App\Classes\ValueObjects\Constants\TransactionDetailType;
|
||||
use App\Http\Resources\TransactionWithStorageResource;
|
||||
use App\Models\Order;
|
||||
@@ -163,6 +164,7 @@ class CheckStorageInvoiceTransactionProcessor
|
||||
if ($transport) {
|
||||
$schedule = $transport->schedules->last();
|
||||
if ($schedule) {
|
||||
Log::channel('storage_invoices')->info('schedule: '.json_encode($schedule));
|
||||
return $schedule->eta;
|
||||
}
|
||||
}
|
||||
@@ -176,11 +178,14 @@ class CheckStorageInvoiceTransactionProcessor
|
||||
$pricePerCBM = 3;
|
||||
$resultNumberOfDaysFree = 10;
|
||||
$dt1 = $eta->copy()->addDay()->startOfDay();
|
||||
$resultStartDate = $dt1->format('Y-m-d');
|
||||
$currentDatetime = Carbon::now();
|
||||
$dt2 = $currentDatetime->copy()->addDay()->startOfDay();
|
||||
$resultCurrentDate = $dt2->format('Y-m-d H:i:s');
|
||||
$dt2 = Carbon::now()->copy()->addDay()->startOfDay();
|
||||
$interval = Carbon::parse($dt2)->diff($dt1);
|
||||
Log::channel('storage_invoices')->info('eta: '.json_encode($eta));
|
||||
Log::channel('storage_invoices')->info('dt1: '.json_encode($dt1));
|
||||
Log::channel('storage_invoices')->info('dt2: '.json_encode($dt2));
|
||||
Log::channel('storage_invoices')->info('interval: '.json_encode($interval));
|
||||
Log::channel('storage_invoices')->info('Carbon now: '.json_encode(Carbon::now()));
|
||||
|
||||
|
||||
$resultNumberOfDaysExceeded = $interval->days - $resultNumberOfDaysFree;
|
||||
$storageInvoice = $destinationWarehousePackage->transactions()->where('transactions.type', TransactionType::STORAGE_INVOICE)->first();
|
||||
@@ -195,14 +200,25 @@ class CheckStorageInvoiceTransactionProcessor
|
||||
$cbm = $cbm + $quantity;
|
||||
}
|
||||
|
||||
$total_tax = 0;
|
||||
$taxPercentage = TaxPercentage::DEFAULT;
|
||||
$price_cbm = $pricePerCBM * $cbm * $resultNumberOfDaysExceeded;
|
||||
Log::channel('storage_invoices')->info('storageInvoice: '.json_encode($storageInvoice).', $transaction->status: '.$transaction->status);
|
||||
$dateToCompare = Carbon::parse(env('SST_START_DATE', '2024-04-01 00:00:00'));
|
||||
|
||||
Log::channel('storage_invoices')->info('dateToCompare: '.json_encode($dateToCompare));
|
||||
if(!$storageInvoice && $resultNumberOfDaysExceeded > 0 && $transaction->status != ApprovalStatus::COMPLETED){
|
||||
Log::channel('storage_invoices')->info('Created $transaction->id: '.$transaction->id);
|
||||
$billNumber = $this->generatesTransactionBillNumber->execute('STOR-');
|
||||
$storageInvoice = $this->createStorageInvoiceTransaction($destinationWarehousePackage, $billNumber, $company_module_id, $price_cbm);
|
||||
|
||||
if (Carbon::now()->isAfter($dateToCompare)) {
|
||||
$taxPercentage = TaxPercentage::SIX_PERCENT;
|
||||
$total_tax = $price_cbm * $taxPercentage / 100;
|
||||
$price_cbm = $price_cbm + $total_tax;
|
||||
}
|
||||
|
||||
$storageInvoice = $this->createStorageInvoiceTransaction($destinationWarehousePackage, $billNumber, $company_module_id, $price_cbm, $total_tax);
|
||||
$storageInvoiceId = $storageInvoice->id;
|
||||
$this->createStorageInvoiceTransactionDetails($storageInvoice, $destinationWarehousePackage, $cbm, $pricePerCBM, $resultNumberOfDaysExceeded);
|
||||
$this->createStorageInvoiceTransactionDetails($storageInvoice, $destinationWarehousePackage, $cbm, $pricePerCBM, $resultNumberOfDaysExceeded, $taxPercentage);
|
||||
}
|
||||
else if($storageInvoice){
|
||||
//Additional handling for giving selected storage invoice a waiver
|
||||
@@ -215,12 +231,18 @@ class CheckStorageInvoiceTransactionProcessor
|
||||
$paymentStorageTransaction = $storageInvoice->transactions()->where('transactions.type', TransactionType::PAYMENT)->where('transactions.status', ApprovalStatus::APPROVED)->first();
|
||||
if($paymentStorageTransaction){
|
||||
$dateStorageInvoicePaid = $paymentStorageTransaction->created_at->copy()->addDay()->startOfDay();
|
||||
Log::channel('storage_invoices')->info('dateStorageInvoicePaid: '.$dateStorageInvoicePaid.', resultCurrentDate: '.$resultCurrentDate);
|
||||
Log::channel('storage_invoices')->info('dateStorageInvoicePaid: '.$dateStorageInvoicePaid.', resultCurrentDate: '.$dt2->format('Y-m-d H:i:s'));
|
||||
$intervalRecalculate = Carbon::parse($dateStorageInvoicePaid)->diff($dt1);
|
||||
$resultNumberOfDaysExceeded = $intervalRecalculate->days - $resultNumberOfDaysFree;
|
||||
$price_cbm = $pricePerCBM * $cbm * $resultNumberOfDaysExceeded;
|
||||
}
|
||||
|
||||
if (Carbon::now()->isAfter($dateToCompare)) {
|
||||
$taxPercentage = TaxPercentage::SIX_PERCENT;
|
||||
$total_tax = $price_cbm * $taxPercentage / 100;
|
||||
$price_cbm = $price_cbm + $total_tax;
|
||||
}
|
||||
|
||||
$amount = $storageInvoice->amount;
|
||||
$epsilon = 0.0001; // Tolerance for the comparison
|
||||
Log::channel('storage_invoices')->info('Update $transaction->id: '.$transaction->id);
|
||||
@@ -246,9 +268,10 @@ class CheckStorageInvoiceTransactionProcessor
|
||||
|
||||
if($proceedToUpdate || ($pricePerCBM == 0 && $amount != 0)){
|
||||
Log::channel('storage_invoices')->info('proceedToUpdate');
|
||||
$storageInvoice = $this->updateStorageInvoiceTransaction($storageInvoice, $price_cbm);
|
||||
|
||||
$storageInvoice = $this->updateStorageInvoiceTransaction($storageInvoice, $price_cbm, $total_tax);
|
||||
$invoiceTransactionDetails = $storageInvoice->transactionDetails()->first();
|
||||
$this->updateStorageInvoiceTransactionDetails($invoiceTransactionDetails, $destinationWarehousePackage, $cbm, $pricePerCBM, $resultNumberOfDaysExceeded);
|
||||
$this->updateStorageInvoiceTransactionDetails($invoiceTransactionDetails, $destinationWarehousePackage, $cbm, $pricePerCBM, $resultNumberOfDaysExceeded, $taxPercentage);
|
||||
}
|
||||
|
||||
$storageInvoiceId = $storageInvoice->id;
|
||||
@@ -260,8 +283,8 @@ class CheckStorageInvoiceTransactionProcessor
|
||||
'storageInvoiceId' => $storageInvoiceId,
|
||||
'numberOfDaysExceeded' => $resultNumberOfDaysExceeded,
|
||||
'numberOfDaysFree' => $resultNumberOfDaysFree,
|
||||
'startDate' => $resultStartDate,
|
||||
'currentDate' => $resultCurrentDate,
|
||||
'startDate' => $dt1->format('Y-m-d'),
|
||||
'currentDate' => $dt2->format('Y-m-d H:i:s'),
|
||||
'cbm' => $cbm,
|
||||
'pricePerCBM' => $pricePerCBM,
|
||||
'storageInvoice' => new TransactionWithStorageResource($storageInvoice)
|
||||
@@ -328,7 +351,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]);
|
||||
@@ -356,7 +379,7 @@ class CheckStorageInvoiceTransactionProcessor
|
||||
}
|
||||
}
|
||||
|
||||
private function updateStorageInvoiceTransaction(Transaction $transaction, float $totalAmount){
|
||||
private function updateStorageInvoiceTransaction(Transaction $transaction, float $totalAmount, float $totalTax){
|
||||
|
||||
$object = new TransactionObject(
|
||||
$transaction->bill_no,
|
||||
@@ -370,7 +393,7 @@ class CheckStorageInvoiceTransactionProcessor
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
$totalTax,
|
||||
0,
|
||||
null,
|
||||
ApprovalStatus::APPROVED
|
||||
@@ -382,18 +405,19 @@ class CheckStorageInvoiceTransactionProcessor
|
||||
return $invoice_transaction;
|
||||
}
|
||||
|
||||
private function updateStorageInvoiceTransactionDetails($invoice_transaction_details, PackingList $packing_list, $cbm, $pricePerCBM, $numberOfDays){
|
||||
private function updateStorageInvoiceTransactionDetails($invoice_transaction_details, PackingList $packing_list, $cbm, $pricePerCBM, $numberOfDays, $taxPercentage){
|
||||
$object_detail = new TransactionDetailObject(
|
||||
'STORAGE_FEE',
|
||||
TransactionDetailType::STORAGE_FEE.' for '.$numberOfDays. ' days * RM'.$pricePerCBM.'<br>'.round($packing_list->packages->where('type', '!=', PackageType::OVER_WEIGHT)->sum('quantity'), 3).' CTNS - '.round($cbm, 3).' CBM',
|
||||
$cbm,
|
||||
$pricePerCBM * $numberOfDays
|
||||
$pricePerCBM * $numberOfDays,
|
||||
$taxPercentage
|
||||
);
|
||||
|
||||
$this->updatesTransactionDetail->execute($invoice_transaction_details, $object_detail);
|
||||
}
|
||||
|
||||
private function createStorageInvoiceTransaction(PackingList $packing_list, string $billNumber, int $companyModuleId, float $totalAmount){
|
||||
private function createStorageInvoiceTransaction(PackingList $packing_list, string $billNumber, int $companyModuleId, float $totalAmount, float $totalTax){
|
||||
|
||||
$object = new TransactionObject(
|
||||
$billNumber,
|
||||
@@ -407,7 +431,7 @@ class CheckStorageInvoiceTransactionProcessor
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
$totalTax,
|
||||
0,
|
||||
null,
|
||||
ApprovalStatus::APPROVED
|
||||
@@ -419,12 +443,13 @@ class CheckStorageInvoiceTransactionProcessor
|
||||
return $invoice_transaction;
|
||||
}
|
||||
|
||||
private function createStorageInvoiceTransactionDetails($invoice_transaction, PackingList $packing_list, $cbm, $pricePerCBM, $numberOfDays){
|
||||
private function createStorageInvoiceTransactionDetails($invoice_transaction, PackingList $packing_list, $cbm, $pricePerCBM, $numberOfDays, $taxPercentage){
|
||||
$object_detail = new TransactionDetailObject(
|
||||
'STORAGE_FEE',
|
||||
TransactionDetailType::STORAGE_FEE.' for '.$numberOfDays. ' days * RM'.$pricePerCBM.'<br>'.round($packing_list->packages->where('type', '!=', PackageType::OVER_WEIGHT)->sum('quantity'), 3).' CTNS - '.round($cbm, 3).' CBM',
|
||||
$cbm,
|
||||
$pricePerCBM * $numberOfDays
|
||||
$pricePerCBM * $numberOfDays,
|
||||
$taxPercentage
|
||||
);
|
||||
|
||||
$this->createsTransactionDetail->execute($invoice_transaction, $object_detail);
|
||||
|
||||
@@ -22,14 +22,17 @@ use App\Classes\ValueObjects\Constants\PaymentMethodType;
|
||||
use App\Classes\ValueObjects\Constants\ApprovalStatus;
|
||||
use App\Classes\ValueObjects\Constants\PackageType;
|
||||
use App\Classes\ValueObjects\Constants\SegmentConstants;
|
||||
use App\Classes\ValueObjects\Constants\TaxPercentage;
|
||||
use App\Classes\ValueObjects\Constants\TransactionDetailType;
|
||||
|
||||
use App\Models\CompanyModule;
|
||||
use App\Models\Document;
|
||||
use App\Models\PackingList;
|
||||
use App\Models\Transaction;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Mccarlosen\LaravelMpdf\Facades\LaravelMpdf;
|
||||
|
||||
class CreateInvoiceTransactionProcessor
|
||||
@@ -171,6 +174,16 @@ class CreateInvoiceTransactionProcessor
|
||||
|
||||
$billNumber = $this->generatesTransactionBillNumber->execute('SHIP-');
|
||||
|
||||
$total_tax = 0;
|
||||
$taxPercentage = TaxPercentage::DEFAULT;
|
||||
$dateToCompare = Carbon::parse(env('SST_START_DATE', '2024-04-01 00:00:00'));
|
||||
$shippingInvoiceTransactionCreatedDate = Carbon::now();
|
||||
if ($shippingInvoiceTransactionCreatedDate->isAfter($dateToCompare)) {
|
||||
$taxPercentage = TaxPercentage::SIX_PERCENT;
|
||||
$total_tax = $total_cbm * $taxPercentage / 100;
|
||||
$total_cbm = $total_cbm + $total_tax;
|
||||
}
|
||||
|
||||
$object = new TransactionObject(
|
||||
$billNumber,
|
||||
TransactionType::SHIPPING_INVOICE,
|
||||
@@ -183,7 +196,7 @@ class CreateInvoiceTransactionProcessor
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
$total_tax,
|
||||
0,
|
||||
null,
|
||||
ApprovalStatus::PENDING_SUBMISSION
|
||||
@@ -196,7 +209,8 @@ class CreateInvoiceTransactionProcessor
|
||||
'SHIPPING_FEE',
|
||||
TransactionDetailType::SHIPPING_FEE.'<br>'.round($packing_list->packages->where('type', '!=', PackageType::OVER_WEIGHT)->sum('quantity'), 3).' CTNS - '.round($cbm, 3).' CBM',
|
||||
$cbm,
|
||||
$price_cbm
|
||||
$price_cbm,
|
||||
$taxPercentage
|
||||
);
|
||||
|
||||
$this->createsTransactionDetail->execute($invoice_transaction, $object_detail);
|
||||
@@ -206,7 +220,8 @@ class CreateInvoiceTransactionProcessor
|
||||
'OVER_WEIGHT_CHARGES',
|
||||
TransactionDetailType::OVER_WEIGHT_CHARGES,
|
||||
$over_weight_cbm,
|
||||
$price_cbm
|
||||
$price_cbm,
|
||||
$taxPercentage
|
||||
);
|
||||
|
||||
$this->createsTransactionDetail->execute($invoice_transaction, $object_detail);
|
||||
@@ -217,7 +232,8 @@ class CreateInvoiceTransactionProcessor
|
||||
'MIN_CBM_CHARGES',
|
||||
TransactionDetailType::MIN_CBM_CHARGES,
|
||||
$minimum_charge,
|
||||
$price_cbm
|
||||
$price_cbm,
|
||||
$taxPercentage
|
||||
);
|
||||
|
||||
$this->createsTransactionDetail->execute($invoice_transaction, $object_detail);
|
||||
|
||||
+188
@@ -0,0 +1,188 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace App\Classes\Modules\Transactions\Processors;
|
||||
|
||||
use App\Classes\Exceptions\MalformedRequestException;
|
||||
use App\Classes\Modules\Transactions\Services\FetchesTransaction;
|
||||
use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber;
|
||||
use App\Classes\Modules\Transactions\Services\CreatesPaymentTransaction;
|
||||
use App\Classes\Modules\Transactions\Services\CreatesTransactionDetail;
|
||||
use App\Classes\Modules\Billplzs\Services\CreatesBillplzBill;
|
||||
use App\Classes\Modules\Transactions\Services\CreatesTransactionableTransaction;
|
||||
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject;
|
||||
use App\Classes\ValueObjects\Constants\TransactionType;
|
||||
use App\Classes\ValueObjects\Constants\PaymentMethodType;
|
||||
use App\Classes\ValueObjects\Constants\ApprovalStatus;
|
||||
use App\Classes\Modules\Wallets\Services\UpdatesWalletBalance;
|
||||
use App\Models\Transaction;
|
||||
use App\Models\Wallet;
|
||||
use App\Classes\Modules\Orders\Processors\UpdateDoFromVTPortalProcessor;
|
||||
use App\Classes\Modules\Orders\Processors\UpdateDoFromYDPortalProcessor;
|
||||
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
//DATE: 20240616
|
||||
//THIS IS A ONE TIME FIX PROCESSOR MEANT TO FIX A GROUP PAYMENT THAT GOT STUCK: https://izyim.cief-malaysia.com/customer/943GCC/payment-and-billing
|
||||
//TRNASACTION WITH ID: 16803
|
||||
//GROUP WITH ID: 609
|
||||
|
||||
class CreatePaymentTransactionOneTimeFixProcessor
|
||||
{
|
||||
|
||||
/** @var GeneratesTransactionBillNumber */
|
||||
private $generatesTransactionBillNumber;
|
||||
|
||||
/** @var CreatesPaymentTransaction */
|
||||
private $createsPaymentTransaction;
|
||||
|
||||
/** @var CreatesBillplzBill */
|
||||
private $createsBillplzBill;
|
||||
|
||||
/** @var CreatesTransactionableTransaction */
|
||||
private $createsTransactionableTransaction;
|
||||
|
||||
/** @var UpdatesWalletBalance */
|
||||
private $updatesWalletBalance;
|
||||
|
||||
/** @var UpdateDoFromVTPortalProcessor */
|
||||
private $updateDoFromVTPortalProcessor;
|
||||
|
||||
/** @var UpdateDoFromYDPortalProcessor */
|
||||
private $updateDoFromYDPortalProcessor ;
|
||||
|
||||
/** @var UpdatesTransactionStatus */
|
||||
private $updatesTransactionStatus ;
|
||||
|
||||
/**
|
||||
* @param FetchesTransaction $fetchesTransaction,
|
||||
* @param GeneratesTransactionBillNumber $generatesTransactionBillNumber,
|
||||
* @param CreatesPaymentTransaction $createsPaymentTransaction
|
||||
* @param CreatesTransactionDetail $createsTransactionDetail
|
||||
* @param CreatesBillplzBill $createsBillplzBil
|
||||
* @param CreatesTransactionableTransaction $createsTransactionableTransaction
|
||||
* @param UpdatesWalletBalance $updatesWalletBalance
|
||||
* @param UpdateDoFromVTPortalProcessor $updateDoFromVTPortalProcessor
|
||||
* @param UpdateDoFromYDPortalProcessor $updateDoFromYDPortalProcessor
|
||||
* @param UpdatesTransactionStatus $updatesTransactionStatus
|
||||
*/
|
||||
public function __construct(
|
||||
GeneratesTransactionBillNumber $generatesTransactionBillNumber,
|
||||
CreatesPaymentTransaction $createsPaymentTransaction,
|
||||
CreatesBillplzBill $createsBillplzBill,
|
||||
CreatesTransactionableTransaction $createsTransactionableTransaction,
|
||||
UpdatesWalletBalance $updatesWalletBalance,
|
||||
UpdateDoFromVTPortalProcessor $updateDoFromVTPortalProcessor,
|
||||
UpdateDoFromYDPortalProcessor $updateDoFromYDPortalProcessor,
|
||||
UpdatesTransactionStatus $updatesTransactionStatus
|
||||
)
|
||||
{
|
||||
$this->generatesTransactionBillNumber = $generatesTransactionBillNumber;
|
||||
$this->createsPaymentTransaction = $createsPaymentTransaction;
|
||||
$this->createsBillplzBill = $createsBillplzBill;
|
||||
$this->createsTransactionableTransaction = $createsTransactionableTransaction;
|
||||
$this->updatesWalletBalance = $updatesWalletBalance;
|
||||
$this->updateDoFromVTPortalProcessor = $updateDoFromVTPortalProcessor;
|
||||
$this->updateDoFromYDPortalProcessor = $updateDoFromYDPortalProcessor;
|
||||
$this->updatesTransactionStatus = $updatesTransactionStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws MalformedRequestException
|
||||
*/
|
||||
public function execute(Transaction $invoice, $payment_method, $bank_code, $date, $run = true)
|
||||
{
|
||||
$amount = $invoice->amount;
|
||||
Log::info($invoice->owner);
|
||||
$company_module = $invoice->owner->owner->companyModule()->first();
|
||||
$approvalStatus = ApprovalStatus::PENDING_SUBMISSION;
|
||||
$billNumber = $this->generatesTransactionBillNumber->execute('PYMT-');
|
||||
$payment_reference = null;
|
||||
|
||||
if ($payment_method == PaymentMethodType::PAYMENT_GATEWAY) {
|
||||
|
||||
// create billplz transaction
|
||||
$payment_method = PaymentMethodType::PAYMENT_GATEWAY;
|
||||
$billPlzBill = $this->createsBillplzBill->execute(
|
||||
$company_module->name,
|
||||
(app()->environment(['production'])) ? $company_module->employees()->first()->email : 'uldvstar@gmail.com',
|
||||
'This payment is for the invoice number . ' . $billNumber,
|
||||
$amount,
|
||||
$billNumber,
|
||||
$bank_code,
|
||||
true
|
||||
);
|
||||
|
||||
$payment_reference = $billPlzBill->id;
|
||||
}
|
||||
else if ($payment_method === PaymentMethodType::WALLET) {
|
||||
/** @var Wallet $wallet */
|
||||
$wallet = $company_module->wallets()->first();
|
||||
|
||||
|
||||
// if((float) number_format(($wallet->amount - $amount),2) < 0){
|
||||
// throw new MalformedRequestException('Insufficient wallet balance. Please Top up your wallet.');
|
||||
// }
|
||||
|
||||
$walletPaymentBillNumber = $this->generatesTransactionBillNumber->execute('PYMT-');
|
||||
|
||||
$transaction_object = new TransactionObject($walletPaymentBillNumber, TransactionType::PAYMENT, 1, $company_module->id, 1, PaymentMethodType::WALLET, $amount, $amount, 1, 1, 1, 0, 0, null, ApprovalStatus::APPROVED, [], '');
|
||||
$transaction = $this->createsTransactionableTransaction->execute($wallet, $transaction_object);
|
||||
$transaction->created_at = $date;
|
||||
$transaction->updated_at = $date;
|
||||
$transaction->save();
|
||||
|
||||
$payment_reference = $walletPaymentBillNumber;
|
||||
|
||||
$this->updatesWalletBalance->execute($wallet, ($amount * -1));
|
||||
|
||||
if($run)
|
||||
{
|
||||
$packingList = $invoice->owner;
|
||||
$order = $packingList->owner;
|
||||
$packingList->status = ApprovalStatus::APPROVED;
|
||||
$packingList->save();
|
||||
|
||||
if(app()->environment('production')){
|
||||
$this->updateDoFromVTPortalProcessor->execute($packingList);
|
||||
$this->updateDoFromYDPortalProcessor->execute($packingList);
|
||||
}
|
||||
}
|
||||
|
||||
// later use this variabke to create a approved payment transaction
|
||||
$approvalStatus = ApprovalStatus::APPROVED;
|
||||
|
||||
// update invoice to completed
|
||||
if($run){
|
||||
$this->updatesTransactionStatus->execute($invoice, ApprovalStatus::COMPLETED);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$payment_method = PaymentMethodType::CASH;
|
||||
}
|
||||
|
||||
$object = new TransactionObject(
|
||||
$billNumber,
|
||||
TransactionType::PAYMENT,
|
||||
$company_module->id,
|
||||
1,
|
||||
1,
|
||||
$payment_method,
|
||||
$amount,
|
||||
$amount,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
null,
|
||||
$approvalStatus,
|
||||
null,
|
||||
$payment_reference
|
||||
);
|
||||
|
||||
$payment_transaction = $this->createsPaymentTransaction->execute($invoice, $object);
|
||||
|
||||
return $payment_transaction;
|
||||
}
|
||||
}
|
||||
@@ -114,7 +114,7 @@ class CreatePaymentTransactionProcessor
|
||||
/** @var Wallet $wallet */
|
||||
$wallet = $company_module->wallets()->first();
|
||||
|
||||
if((float) number_format(($wallet->amount - $amount),2) < 0){
|
||||
if((float) number_format(($wallet->amount - $amount),2) < -0.01){
|
||||
throw new MalformedRequestException('Insufficient wallet balance. Please Top up your wallet.');
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -9,6 +9,7 @@ use App\Classes\ValueObjects\Constants\ApprovalStatus;
|
||||
use App\Classes\ValueObjects\Constants\SegmentConstants;
|
||||
use App\Classes\ValueObjects\Constants\TransactionType;
|
||||
use App\Classes\ValueObjects\Constants\PaymentMethodType;
|
||||
use App\Classes\ValueObjects\Constants\TaxPercentage;
|
||||
use App\Models\Order;
|
||||
|
||||
class CreateShippingCostTransactionProcessor
|
||||
@@ -57,7 +58,8 @@ class CreateShippingCostTransactionProcessor
|
||||
TransactionType::SHIPPING_COST,
|
||||
'Shipping Cost',
|
||||
$quantity,
|
||||
$totalShippingCost/$totalCBM
|
||||
$totalShippingCost/$totalCBM,
|
||||
TaxPercentage::SIX_PERCENT
|
||||
);
|
||||
|
||||
$shippingCostTransaction = $this->createsShippingCostTransaction->execute($order, $transactionObject, $transactionDetailObject);
|
||||
|
||||
+12
-2
@@ -16,6 +16,8 @@ use App\Classes\Modules\Documents\Services\CreatesFiles;
|
||||
use App\Classes\Modules\Documents\Services\CreatesDocument;
|
||||
use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject;
|
||||
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class CreateStorageInvoiceDocTransactionFixProcessor
|
||||
{
|
||||
@@ -51,9 +53,17 @@ class CreateStorageInvoiceDocTransactionFixProcessor
|
||||
/** @var Transaction $invoice_transaction */
|
||||
$invoice_transaction = $packingList->transactions()->where('transactions.type', TransactionType::STORAGE_INVOICE)->whereIn('status', [ApprovalStatus::COMPLETED])->first();
|
||||
|
||||
// $this->updatesTransactionStatus->execute($invoice_transaction, ApprovalStatus::APPROVED);
|
||||
// $this->updatesTransactionStatus->execute($invoice_transaction, ApprovalStatus::APPROVED);
|
||||
$view = 'pages.pdfs.shipping_invoice';
|
||||
$dateToCompare = Carbon::parse(env('SST_START_DATE', '2024-04-01 00:00:00'));
|
||||
Log::info('$dateToCompare 2: '.$dateToCompare);
|
||||
$storageInvoiceTransactionCreatedDate = Carbon::parse($invoice_transaction->created_at);
|
||||
Log::info('$storageInvoiceTransactionCreatedDate 2: '.$storageInvoiceTransactionCreatedDate);
|
||||
if ($storageInvoiceTransactionCreatedDate->isAfter($dateToCompare) && $invoice_transaction->tax > 0) {
|
||||
$view = 'pages.pdfs.shipping_invoice_sst';
|
||||
}
|
||||
|
||||
$transaction_invoice_pdf = LaravelMpdf::loadView('pages.pdfs.shipping_invoice', ['invoice_transaction' => $invoice_transaction]);
|
||||
$transaction_invoice_pdf = LaravelMpdf::loadView($view, ['invoice_transaction' => $invoice_transaction]);
|
||||
|
||||
$document_object = new DocumentObject(
|
||||
DocumentType::STORAGE_INVOICE,
|
||||
|
||||
+12
-1
@@ -16,6 +16,8 @@ use App\Classes\Modules\Documents\Services\CreatesFiles;
|
||||
use App\Classes\Modules\Documents\Services\CreatesDocument;
|
||||
use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject;
|
||||
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class CreateStorageInvoiceDocTransactionProcessor
|
||||
{
|
||||
@@ -53,7 +55,16 @@ class CreateStorageInvoiceDocTransactionProcessor
|
||||
|
||||
// $this->updatesTransactionStatus->execute($invoice_transaction, ApprovalStatus::APPROVED);
|
||||
|
||||
$transaction_invoice_pdf = LaravelMpdf::loadView('pages.pdfs.shipping_invoice', ['invoice_transaction' => $invoice_transaction]);
|
||||
$view = 'pages.pdfs.shipping_invoice';
|
||||
$dateToCompare = Carbon::parse(env('SST_START_DATE', '2024-04-01 00:00:00'));
|
||||
Log::info('$dateToCompare: '.$dateToCompare);
|
||||
$storageInvoiceTransactionCreatedDate = Carbon::parse($invoice_transaction->created_at);
|
||||
Log::info('$storageInvoiceTransactionCreatedDate: '.$storageInvoiceTransactionCreatedDate);
|
||||
if ($storageInvoiceTransactionCreatedDate->isAfter($dateToCompare) && $invoice_transaction->tax > 0) {
|
||||
$view = 'pages.pdfs.shipping_invoice_sst';
|
||||
}
|
||||
|
||||
$transaction_invoice_pdf = LaravelMpdf::loadView($view, ['invoice_transaction' => $invoice_transaction]);
|
||||
|
||||
$document_object = new DocumentObject(
|
||||
DocumentType::STORAGE_INVOICE,
|
||||
|
||||
@@ -44,6 +44,8 @@ class CreatesShippingCostTransaction extends AbstractUpdateRelationshipRecord
|
||||
$model->quantity = $transactionDetailObject->getQuantity();
|
||||
$model->price = $transactionDetailObject->getPrice();
|
||||
$model->amount = $transactionDetailObject->getAmount();
|
||||
$model->tax_amount = $transactionDetailObject->getTaxAmount();
|
||||
$model->tax_percentage = $transactionDetailObject->getTaxPercentage();
|
||||
|
||||
return $this->handler($transaction->transactionDetails(), $model);
|
||||
|
||||
|
||||
@@ -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
|
||||
{
|
||||
@@ -35,4 +37,4 @@ class CreatesTransaction extends AbstractUpdateRelationshipRecord
|
||||
|
||||
return $this->handler($packing_list->transactions(), $model);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,8 +23,10 @@ class CreatesTransactionDetail extends AbstractUpdateRelationshipRecord
|
||||
$model->quantity = $object->getQuantity();
|
||||
$model->price = $object->getPrice();
|
||||
$model->amount = $object->getAmount();
|
||||
$model->tax_amount = $object->getTaxAmount();
|
||||
$model->tax_percentage = $object->getTaxPercentage();
|
||||
|
||||
return $this->handler($transaction->transactionDetails(), $model);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,8 +20,10 @@ class UpdatesTransactionDetail extends AbstractUpdateRecord
|
||||
$transactionDetail->quantity = $object->getQuantity();
|
||||
$transactionDetail->price = $object->getPrice();
|
||||
$transactionDetail->amount = $object->getAmount();
|
||||
$transactionDetail->tax_amount = $object->getTaxAmount();
|
||||
$transactionDetail->tax_percentage = $object->getTaxPercentage();
|
||||
|
||||
return $this->handler($transactionDetail);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ use App\Classes\Modules\Transactions\Services\CreatesTransactionableTransaction;
|
||||
use App\Classes\Modules\Wallets\DataTransferObjects\WalletObject;
|
||||
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject;
|
||||
use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber;
|
||||
use App\Classes\Modules\Wallets\Services\UpdatesWalletBalance;
|
||||
use App\Models\CompanyModule;
|
||||
|
||||
class CreditWalletProcessor
|
||||
@@ -36,6 +37,9 @@ class CreditWalletProcessor
|
||||
|
||||
/** @var UpdatesWallet */
|
||||
private $updatesWallet;
|
||||
|
||||
/** @var UpdatesWalletBalance */
|
||||
private $updatesWalletBalance;
|
||||
|
||||
/**
|
||||
* CreateWalletLogic constructor.
|
||||
@@ -45,6 +49,7 @@ class CreditWalletProcessor
|
||||
* @param CreatesTransaction $createsTransaction
|
||||
* @param CreatesTransactionableTransaction $createsTransactionableTransaction
|
||||
* @param UpdatesWallet $updatesWallet
|
||||
* @param UpdatesWalletBalance $updatesWalletBalance
|
||||
*/
|
||||
public function __construct(
|
||||
GeneratesWalletCode $generatesWalletCode,
|
||||
@@ -52,7 +57,8 @@ class CreditWalletProcessor
|
||||
GeneratesTransactionBillNumber $generatesTransactionBillNumber,
|
||||
CreatesTransaction $createsTransaction,
|
||||
CreatesTransactionableTransaction $createsTransactionableTransaction,
|
||||
UpdatesWallet $updatesWallet
|
||||
UpdatesWallet $updatesWallet,
|
||||
UpdatesWalletBalance $updatesWalletBalance
|
||||
)
|
||||
{
|
||||
$this->generatesWalletCode = $generatesWalletCode;
|
||||
@@ -61,6 +67,7 @@ class CreditWalletProcessor
|
||||
$this->createsTransaction = $createsTransaction;
|
||||
$this->createsTransactionableTransaction = $createsTransactionableTransaction;
|
||||
$this->updatesWallet = $updatesWallet;
|
||||
$this->updatesWalletBalance = $updatesWalletBalance;
|
||||
}
|
||||
|
||||
|
||||
@@ -87,11 +94,13 @@ class CreditWalletProcessor
|
||||
$transaction_object = new TransactionObject($billNumber, $transactionType === 2 ? TransactionType::DEBIT_NOTE : TransactionType::CREDIT_NOTE, 1, $wallet->owner->id, 1, PaymentMethodType::CASH, $amount, $amount, 1, 1, 1, 0, 0, null, ApprovalStatus::APPROVED, [], $reference);
|
||||
$transaction = $this->createsTransactionableTransaction->execute($wallet, $transaction_object);
|
||||
|
||||
$updateWalletAmount = $transactionType === 2 ? ($wallet->amount - $transaction->amount) : ($wallet->amount + $transaction->amount);
|
||||
$this->updatesWalletBalance->execute($wallet, $transaction->amount);
|
||||
|
||||
$walletObject = new WalletObject($wallet->owner->id, $wallet->currency_id, $wallet->code, $updateWalletAmount);
|
||||
// $updateWalletAmount = $transactionType === 2 ? ($wallet->amount - $transaction->amount) : ($wallet->amount + $transaction->amount);
|
||||
|
||||
$wallet = $this->updatesWallet->execute($wallet, $walletObject);
|
||||
// $walletObject = new WalletObject($wallet->owner->id, $wallet->currency_id, $wallet->code, $updateWalletAmount);
|
||||
|
||||
// $wallet = $this->updatesWallet->execute($wallet, $walletObject);
|
||||
|
||||
return $wallet;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ use App\Classes\ValueObjects\Constants\TransactionType;
|
||||
use App\Models\PackingList;
|
||||
use App\Models\User;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class InvoiceIssuedEmail extends AbstractEmail
|
||||
@@ -35,10 +36,14 @@ class InvoiceIssuedEmail extends AbstractEmail
|
||||
$invoice = $this->packingList->transactions()->where('type', TransactionType::SHIPPING_INVOICE)->where('status', ApprovalStatus::APPROVED)->first();
|
||||
$invoiceDocument = $invoice->documents()->first()->files;
|
||||
|
||||
// $fileContent = Storage::disk('documents')->get($invoiceDocument->first()->file->file_info->original->file);
|
||||
$filePath = storage_path('app/documents/' . $invoiceDocument->first()->file->file_info->original->file);
|
||||
|
||||
Log::info('InvoiceIssuedEmail sent - Att: '.$this->user->name.' - Invoice for order no.'. $this->packingList->owner->reference);
|
||||
|
||||
return (new MailMessage)
|
||||
->subject('Att: '.$this->user->name.' - Invoice for order no.'. $this->packingList->owner->reference)
|
||||
->attach(Storage::disk('documents')->get($invoiceDocument->first()->file->file_info->original->file), [
|
||||
->attach($filePath, [
|
||||
'as' => 'name.pdf',
|
||||
'mime' => 'application/pdf',
|
||||
])->view('emails.shipment.invoice', ['user' => $this->user, 'packingList' => $this->packingList]);
|
||||
|
||||
@@ -9,6 +9,7 @@ use App\Models\PackingList;
|
||||
use App\Models\PasswordReset;
|
||||
use App\Models\User;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class ShipmentDepartureEmail extends AbstractEmail
|
||||
@@ -40,10 +41,14 @@ class ShipmentDepartureEmail extends AbstractEmail
|
||||
|
||||
$invoiceDocument = $invoice->documents()->first()->files;
|
||||
|
||||
// $fileContent = Storage::disk('documents')->get($invoiceDocument->first()->file->file_info->original->file);
|
||||
$filePath= storage_path('app/documents/' . $invoiceDocument->first()->file->file_info->original->file);
|
||||
|
||||
Log::info('ShipmentDepartureEmail sent - Att: '.$this->user->name.' - Invoice for order no.'. $this->packingList->owner->reference);
|
||||
|
||||
return (new MailMessage)
|
||||
->subject('Your packages are on the way to malaysia - Invoice pending payment for order no.'. $this->packingList->owner->reference)
|
||||
->attach(Storage::disk('documents')->get($invoiceDocument->first()->file->file_info->original->file), [
|
||||
->attach($filePath, [
|
||||
'as' => 'name.pdf',
|
||||
'mime' => 'application/pdf',
|
||||
])->bcc(['email_test@cief-malaysia.com'])->view('emails.shipment.ETD', ['user' => $this->user, 'packingList' => $this->packingList]);
|
||||
|
||||
@@ -10,4 +10,6 @@ final class RemarkTypes
|
||||
|
||||
public const EXTERNAL = 1;
|
||||
|
||||
}
|
||||
public const ADDRESS_EXTRA_COLUMNS = 2;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace App\Classes\ValueObjects\Constants;
|
||||
|
||||
final class TaxPercentage {
|
||||
|
||||
public const DEFAULT = 0;
|
||||
|
||||
public const NO_TAX = 0;
|
||||
|
||||
public const SIX_PERCENT = 6;
|
||||
}
|
||||
@@ -13,4 +13,6 @@ final class TransactionDetailType {
|
||||
public const CUSTOM_CHARGES = 'Custom charges';
|
||||
|
||||
public const STORAGE_FEE = 'Malaysia Warehouse Storage Fee';
|
||||
|
||||
public const PAY_ON_BEHALF = 'Pay on behalf';
|
||||
}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Classes\Modules\Billplzs\Processors\CallbackBillplzProcessor;
|
||||
use App\Classes\ValueObjects\Constants\ApprovalStatus;
|
||||
use App\Models\Group;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
|
||||
class FixApprovedPaymentFailedGroup extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'fix-approved-payment-failed-group';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Fix all payment is approved or completed but group failed to be updated';
|
||||
|
||||
protected $output = null;
|
||||
|
||||
protected $outputArray = [];
|
||||
|
||||
/** @var CallbackBillplzProcessor */
|
||||
private $callbackBillplzProcessor;
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(CallbackBillplzProcessor $callbackBillplzProcessor)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->callbackBillplzProcessor = $callbackBillplzProcessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
ini_set('memory_limit', '-1');
|
||||
|
||||
$this->outputArray = [];
|
||||
$start = new Carbon();
|
||||
|
||||
$groups = Group::whereNotIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])
|
||||
->whereHas('payment', function ($query) {
|
||||
$query->whereIn('status', [2, 3]);
|
||||
})->get();
|
||||
|
||||
foreach ($groups as $group) {
|
||||
$transaction = $group->payment;
|
||||
|
||||
$response = Http::withBasicAuth(config('billplz.api_key') . ':', '')->get(config('billplz.base_url') . '/api/v3/bills/' . $transaction->payment_reference);
|
||||
|
||||
dump($transaction->payment_reference);
|
||||
|
||||
if ($response->successful()) {
|
||||
$data = $response->json();
|
||||
if ($data['paid']) {
|
||||
$status = ApprovalStatus::PENDING_VERIFICATION;
|
||||
|
||||
if ($data['state'] === 'paid') {
|
||||
$status = ApprovalStatus::APPROVED;
|
||||
}
|
||||
|
||||
$this->info(Carbon::now() . ' : Fixing ' . $transaction->payment_reference);
|
||||
$this->callbackBillplzProcessor->execute($transaction, $status);
|
||||
}
|
||||
} else {
|
||||
$this->info("billplz error</br>");
|
||||
}
|
||||
}
|
||||
|
||||
$end = new Carbon();
|
||||
$elapsedTime = $start->diff($end)->format('%H:%I:%S');
|
||||
|
||||
if ($groups) {
|
||||
$this->info(Carbon::now() . ' : Done . ElapsedTime: ' . $elapsedTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -58,13 +58,20 @@ class FixInvoice extends Command
|
||||
foreach ($orders as $order){
|
||||
$invoices = $order->transactions()->where('transactions.type', TransactionType::SHIPPING_INVOICE)->get();
|
||||
foreach ($invoices as $invoice){
|
||||
|
||||
|
||||
dump($invoice->id);
|
||||
|
||||
|
||||
$invoice->documents()->delete();
|
||||
|
||||
$transaction_invoice_pdf = LaravelMpdf::loadView('pages.pdfs.shipping_invoice', ['invoice_transaction' => $invoice]);
|
||||
|
||||
|
||||
$view = 'pages.pdfs.shipping_invoice';
|
||||
$dateToCompare = Carbon::parse(env('SST_START_DATE', '2024-04-01 00:00:00'));
|
||||
$shippingInvoiceTransactionCreatedDate = Carbon::parse($invoice->created_at);
|
||||
if ($shippingInvoiceTransactionCreatedDate->isAfter($dateToCompare) && $invoice->tax > 0) {
|
||||
$view = 'pages.pdfs.shipping_invoice_sst';
|
||||
}
|
||||
|
||||
$transaction_invoice_pdf = LaravelMpdf::loadView($view, ['invoice_transaction' => $invoice]);
|
||||
|
||||
$document_object = new DocumentObject(
|
||||
DocumentType::SHIPPING_INVOICE,
|
||||
[chunk_split('data:application/pdf;base64,'.base64_encode($transaction_invoice_pdf->output()))],
|
||||
@@ -72,10 +79,10 @@ class FixInvoice extends Command
|
||||
ApprovalStatus::COMPLETED,
|
||||
'shipping_invoice'
|
||||
);
|
||||
|
||||
|
||||
/** @var Document $document */
|
||||
$document = (App()->make(CreatesDocument::class))->execute($invoice, $document_object);
|
||||
|
||||
|
||||
(App()->make(CreatesFiles::class))->execute($document, $document_object);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Classes\Modules\PackingLists\Processors\FetchPackingListsFromYdPortalProcessor;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class FixMissingPackingList extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'fix-missing-packinglist';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Fix Missing Packinglist';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$start_date = '2024-05-05';
|
||||
$end_date = '2024-05-05';
|
||||
|
||||
$start = $start_date ? Carbon::parse($start_date) : null;
|
||||
$end = $end_date ? Carbon::parse($end_date) : null;
|
||||
|
||||
if (!$start || !$end) {
|
||||
return;
|
||||
}
|
||||
|
||||
(App()->make(FetchPackingListsFromYdPortalProcessor::class))->execute($start, $end);
|
||||
}
|
||||
}
|
||||
@@ -55,11 +55,12 @@ class OneTimeTransactionFixBillplzFailedCallback extends Command
|
||||
$this->outputArray = [];
|
||||
$start = new Carbon();
|
||||
|
||||
//This transaction, 15205 has approve payment but not its owner, shipping invoice
|
||||
$transaction = Transaction::whereIn('id', [15205])->first();
|
||||
$this->info(Carbon::now() . ' : One time fix failled callback from billplz for transaction with id 15205 cron started.');
|
||||
//Transaction fix with this one time fix command: 15205, 16803
|
||||
//This transaction, 16803 has approve payment but not its owner, shipping invoice
|
||||
$transaction = Transaction::whereIn('id', [16803])->first();
|
||||
$this->info(Carbon::now() . ' : One time fix failled callback from billplz for transaction with id 16803 cron started.');
|
||||
|
||||
if($transaction && $transaction->id == 15205){
|
||||
if($transaction && $transaction->id == 16803){
|
||||
|
||||
$status = ApprovalStatus::APPROVED;
|
||||
$this->callbackBillplzProcessor->execute($transaction, $status);
|
||||
@@ -68,6 +69,6 @@ class OneTimeTransactionFixBillplzFailedCallback extends Command
|
||||
|
||||
$end = new Carbon();
|
||||
$elapsedTime = $start->diff($end)->format('%H:%I:%S');
|
||||
$this->info(Carbon::now() . ' : One time fix failled callback from billplz for transaction with id 15205 cron ended. ElapsedTime: ' . $elapsedTime);
|
||||
$this->info(Carbon::now() . ' : One time fix failled callback from billplz for transaction with id 16803 cron ended. ElapsedTime: ' . $elapsedTime);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,25 +40,41 @@ class ImportPermitsReminderController
|
||||
$row['reminder_date'] = $this->changeExcelDate($row['reminder_date']);
|
||||
|
||||
$validator = Validator::make($row, [
|
||||
'model' => 'required|unique:permits_reminders,model',
|
||||
'expiry_date' => 'required|date|after_or_equal:today',
|
||||
'reminder_date' => 'required|date|after_or_equal:today',
|
||||
'model' => 'required',
|
||||
// 'expiry_date' => 'required|date|after_or_equal:today',
|
||||
'expiry_date' => 'required|date',
|
||||
// 'reminder_date' => 'required|date|after_or_equal:today',
|
||||
'reminder_date' => 'required|date',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
$row['status'] = 'failed';
|
||||
$row['message'] = $validator->errors()->all();
|
||||
|
||||
$returnArray[] = $row;
|
||||
} else {
|
||||
$row['created_at'] = Carbon::now();
|
||||
$row['updated_at'] = Carbon::now();
|
||||
$successRows[] = $row;
|
||||
$existingRecord = PermitsReminder::where('model', $row['model'])->first();
|
||||
|
||||
if ($existingRecord) {
|
||||
$existingRecord->update([
|
||||
'expiry_date' => $row['expiry_date'],
|
||||
'reminder_date' => $row['reminder_date'],
|
||||
]);
|
||||
|
||||
$row['status'] = 'Updated';
|
||||
$row['message'] = 'Record has been updated';
|
||||
$returnArray[] = $row;
|
||||
} else {
|
||||
// Add to successful rows for batch insertion
|
||||
$row['created_at'] = Carbon::now();
|
||||
$row['updated_at'] = Carbon::now();
|
||||
$successRows[] = $row;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Insert only if there are new successful rows
|
||||
if (!empty($successRows)) {
|
||||
PermitsReminder::insert($successRows); // Insert only if there are successful rows
|
||||
PermitsReminder::insert($successRows);
|
||||
}
|
||||
|
||||
$successCount = count($successRows);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,11 @@ class AddressResource extends JsonResource
|
||||
$outstationPostcodeConstant = $outstationPostcodeConstantObject->isEmpty() ? [] : (array)$outstationPostcodeConstantObject->first()->value;
|
||||
in_array((String)$this->postcode, $outstationPostcodeConstant) ? $postcodeArea = 'OUTSTATION_POSTCODE' : null;
|
||||
|
||||
return [
|
||||
// Handle extra fields
|
||||
$extrafields = $this->addressExtraFields->first();
|
||||
$extrafields = $extrafields ? json_decode($extrafields->content, true) : [];
|
||||
|
||||
$returnArray = [
|
||||
'id' => $this->id,
|
||||
'reference' => $this->reference,
|
||||
'street_one' => $this->street_one,
|
||||
@@ -52,5 +56,12 @@ class AddressResource extends JsonResource
|
||||
])
|
||||
|
||||
];
|
||||
|
||||
// Merge extra fields into the return array
|
||||
if ($extrafields) {
|
||||
$returnArray = array_merge($returnArray, $extrafields);
|
||||
}
|
||||
|
||||
return $returnArray;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,8 @@ class CompanyResource extends JsonResource
|
||||
'last_order' => $companyModule->type === 7 ? new DeliveryOrderResource($companyModule->orders()->orderBy('id', 'DESC')->first()) : new OrderResource($companyModule->orders()->orderBy('id', 'DESC')->first()),
|
||||
'order_count' => $companyModule->orders()->count(),
|
||||
'identification' => new DocumentResource($this->documents->whereIn('document_type', DocumentType::IDENTIFICATION_DOCUMENTS)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED])->first()),
|
||||
'created_at' => $this->created_at->format('d-m-Y')
|
||||
'created_at' => $this->created_at->format('d-m-Y'),
|
||||
'whatsapp' => new ContactResource($this->contacts()->where('reference', 'LIKE', '%Whatsapp%')->orderBy('created_at', 'DESC')->first())
|
||||
|
||||
];
|
||||
|
||||
|
||||
@@ -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
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,9 +32,11 @@ class MappableTransactionWithDetailsResource extends JsonResource
|
||||
|
||||
if ($this->type === TransactionType::PAYMENT) {
|
||||
$order = $this->owner->owner->owner;
|
||||
$data['order_reference'] = $order->reference;
|
||||
$data['debtor_code'] = $order->companyModule->company->debtor;
|
||||
$data['created_at'] = $this->owner->created_at; // invoice date
|
||||
if ($order) {
|
||||
$data['order_reference'] = $order->reference;
|
||||
$data['debtor_code'] = $order->companyModule->company->debtor;
|
||||
$data['created_at'] = $this->owner->created_at; // invoice date
|
||||
}
|
||||
} elseif (in_array($this->type, [TransactionType::GROUP_PAYMENT, TransactionType::TOP_UP])) {
|
||||
$connection = $this->owner->owner->inviters()->withPivot('invitee_reference')->first();
|
||||
$data['marking'] = $connection ? $connection->pivot->invitee_reference : '';
|
||||
@@ -48,17 +50,20 @@ class MappableTransactionWithDetailsResource extends JsonResource
|
||||
if ($payments->count()) {
|
||||
$data['payment_transactions'] = $payments->map(function ($payment) {
|
||||
$order = $payment->owner->owner->owner;
|
||||
return [
|
||||
'id' => $payment->id,
|
||||
'updated_at' => $payment->updated_at,
|
||||
'debtor_code' => $order->companyModule->company->debtor,
|
||||
'order_reference' => $order->reference,
|
||||
'bill_no' => null,
|
||||
'type' => $payment->type,
|
||||
'marking' => null,
|
||||
'amount' => $payment->amount,
|
||||
'created_at' => $this->created_at
|
||||
];
|
||||
|
||||
if ($order) {
|
||||
return [
|
||||
'id' => $payment->id,
|
||||
'updated_at' => $payment->updated_at,
|
||||
'debtor_code' => $order->companyModule->company->debtor,
|
||||
'order_reference' => $order->reference,
|
||||
'bill_no' => null,
|
||||
'type' => $payment->type,
|
||||
'marking' => null,
|
||||
'amount' => $payment->amount,
|
||||
'created_at' => $this->created_at
|
||||
];
|
||||
}
|
||||
})->toArray();
|
||||
} else {
|
||||
$data['status'] = 'error';
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace App\Http\Resources;
|
||||
use App\Classes\ValueObjects\Constants\ApprovalStatus;
|
||||
use App\Classes\ValueObjects\Constants\OrderRoleTypes;
|
||||
use App\Classes\ValueObjects\Constants\PackingListType;
|
||||
use App\Classes\ValueObjects\Constants\RemarkTypes;
|
||||
use App\Classes\ValueObjects\Constants\TransactionType;
|
||||
use App\Classes\ValueObjects\Constants\TransportType;
|
||||
use App\Models\Transaction;
|
||||
@@ -53,7 +54,7 @@ class OrderResource extends JsonResource
|
||||
'invoices' => $this->whenLoaded('packingLists', function() use ($orderId) {
|
||||
return TransactionResource::collection($this->transactions()->whereNotIn('transactions.status', [0, 1])->where('transactions.type', TransactionType::SHIPPING_INVOICE)->get());
|
||||
}),
|
||||
'remarks' => RemarkResource::collection($this->remarks),
|
||||
'remark' => new RemarkResource($this->remarks->first()),
|
||||
'created_at' => $this->created_at->format('d-m-Y')
|
||||
];
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ class SegmentResource extends JsonResource
|
||||
$constant = $this->constants->where('reference', SegmentConstants::CUSTOM_PRICE)->first();
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'name' => $this->name,
|
||||
'name' => ucwords(str_replace('_', ' ', $this->name)),
|
||||
'price' => $constant ? $constant->value[0] : 0
|
||||
];
|
||||
}
|
||||
|
||||
@@ -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')
|
||||
];
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace App\Http\Resources;
|
||||
use App\Classes\ValueObjects\Constants\ApprovalStatus;
|
||||
use App\Classes\ValueObjects\Constants\TransactionType;
|
||||
use App\Models\Group;
|
||||
use App\Models\PackingList;
|
||||
use App\Models\Transaction;
|
||||
use App\Models\Wallet;
|
||||
use Carbon\Carbon;
|
||||
@@ -27,7 +28,9 @@ class TransactionWithStorageResource extends JsonResource
|
||||
$groupPaymentAttemptsFiltered = [];
|
||||
$group_payment_expired = null;
|
||||
$group_payment_history = null;
|
||||
$group_payment_history_query = null;
|
||||
$groupTotalAmount = 0;
|
||||
$payment_history = null;
|
||||
|
||||
if ($this->owner instanceof Transaction) {
|
||||
if ($this->owner) {
|
||||
@@ -43,7 +46,8 @@ class TransactionWithStorageResource extends JsonResource
|
||||
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]));
|
||||
$group_payment_history = GroupForOrderV2Resource::collection($this->groups->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::REJECTED]));
|
||||
$group_payment_history_query = $this->groups->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::REJECTED]);
|
||||
$group_payment_history = GroupForOrderV2Resource::collection($group_payment_history_query);
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -54,9 +58,13 @@ class TransactionWithStorageResource extends JsonResource
|
||||
|
||||
}
|
||||
|
||||
$packingListReference = null;
|
||||
if ($this->owner instanceof PackingList) {
|
||||
$packingListReference = $this->owner->reference;
|
||||
}
|
||||
|
||||
$ts = $this->groups->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION])->last();
|
||||
if ($ts) {
|
||||
if ($ts && $group_payment_history && $group_payment_attempts) {
|
||||
$paymentTransaction = Transaction::where('payment_reference', $ts->reference)->whereIn('status', [ApprovalStatus::PENDING_SUBMISSION])->first();
|
||||
if($paymentTransaction){
|
||||
$groupTotalAmount = (double) $this->amount;
|
||||
@@ -76,6 +84,21 @@ class TransactionWithStorageResource extends JsonResource
|
||||
}
|
||||
|
||||
|
||||
$payment_history = TransactionResource::collection($this->transactions()
|
||||
->payments()
|
||||
->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::COMPLETED, ApprovalStatus::REJECTED])
|
||||
->get());
|
||||
|
||||
//For 'Your Payment Proof' at frontend
|
||||
|
||||
if($group_payment_history_query && count($group_payment_history_query) > 0){
|
||||
if($this->getReferenceForGroupPayment($group_payment_history_query)){
|
||||
foreach ($payment_history as $item) {
|
||||
$item['payment_reference'] = $this->getReferenceForGroupPayment($group_payment_history_query);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'owner_type' => $this->owner_type,
|
||||
@@ -112,18 +135,22 @@ class TransactionWithStorageResource extends JsonResource
|
||||
->payments()->where('status', ApprovalStatus::EXPIRED)
|
||||
->get()
|
||||
),
|
||||
'payment_history' => TransactionResource::collection(
|
||||
$this->transactions()
|
||||
->payments()
|
||||
->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::COMPLETED, ApprovalStatus::REJECTED])
|
||||
->get()
|
||||
),
|
||||
'payment_history' => $payment_history,
|
||||
'remarks' => RemarkResource::collection($this->remarks),
|
||||
'packing_list_reference' => $packingListReference,
|
||||
'storages' => $this->storages ? $this->storages : null, //from middleware
|
||||
'is_waived' => (int) $this->is_waived,
|
||||
'expires_on' => Carbon::parse($this->expires_on)->format('d-m-Y h: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')
|
||||
];
|
||||
}
|
||||
|
||||
private function getReferenceForGroupPayment($groups){
|
||||
if (is_array($groups) && count($groups) > 0) {
|
||||
$firstGroup = $groups[0];
|
||||
return $firstGroup['reference'];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
+10
-1
@@ -4,6 +4,7 @@ namespace App\Models;
|
||||
|
||||
use App\Classes\General\Interfaces\Contactable;
|
||||
use App\Classes\General\Interfaces\Remarkable;
|
||||
use App\Classes\ValueObjects\Constants\RemarkTypes;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
@@ -87,6 +88,14 @@ class Address extends AbstractModel implements Contactable, Remarkable
|
||||
*/
|
||||
public function remarks(): morphMany
|
||||
{
|
||||
return $this->morphMany(Remark::class, 'owner');
|
||||
return $this->morphMany(Remark::class, 'owner')->whereNull('type');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return MorphMany
|
||||
*/
|
||||
public function addressExtraFields(): MorphMany
|
||||
{
|
||||
return $this->morphMany(Remark::class, 'owner')->where('type', RemarkTypes::ADDRESS_EXTRA_COLUMNS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,4 +69,12 @@ class CompanyConnection extends AbstractModel
|
||||
return $this->belongsToMany(Segment::class, (new ConnectionSegment())->getTable(), 'company_connection_id', 'segment_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return belongsToMany
|
||||
*/
|
||||
public function connectionSegments(): HasMany
|
||||
{
|
||||
return $this->hasMany(ConnectionSegment::class, 'company_connection_id');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -84,4 +84,12 @@ class Group extends Model implements Documentable, Transactionable
|
||||
{
|
||||
return $this->BelongsTo(Currency::class, 'original_currency_id', 'id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return hasOne
|
||||
*/
|
||||
public function payment()
|
||||
{
|
||||
return $this->hasOne(Transaction::class, 'payment_reference', 'reference');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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'),
|
||||
@@ -124,6 +130,11 @@ return [
|
||||
'path' => storage_path('logs/laravel_perfex_crm.log'),
|
||||
'level' => 'info',
|
||||
],
|
||||
'wac_webhook' => [
|
||||
'driver' => 'single',
|
||||
'path' => storage_path('logs/wac_webhook.log'),
|
||||
'level' => 'info',
|
||||
],
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
@@ -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=',
|
||||
];
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddColumnsToTransactionDetailsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('transaction_details', function (Blueprint $table) {
|
||||
$table->decimal('tax_amount', 14, 5)->after('amount')->default(0.00);
|
||||
$table->decimal('tax_percentage', 6, 2)->after('tax_amount')->default(0.00);
|
||||
$table->decimal('discount', 14, 5)->after('tax_percentage')->default(0.00);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('transaction_details', function (Blueprint $table) {
|
||||
$table->dropColumn('tax_amount');
|
||||
$table->dropColumn('tax_percentage');
|
||||
$table->dropColumn('discount');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddTypeToRemarksTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('remarks', function (Blueprint $table) {
|
||||
$table->string('type')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('remarks', function (Blueprint $table) {
|
||||
$table->dropColumn('type');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,7 @@
|
||||
"vue": "^2.6.10",
|
||||
"vue-avatar": "^2.1.8",
|
||||
"vue-debounce": "^2.6.0",
|
||||
"vue-multi-select": "^4.6.0",
|
||||
"vue-template-compiler": "^2.6.10",
|
||||
"vue-the-mask": "^0.11.1",
|
||||
"vuelidate": "^0.7.4",
|
||||
|
||||
Vendored
+3
@@ -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);
|
||||
|
||||
@@ -3,14 +3,6 @@
|
||||
<div class="col">
|
||||
<div class="row" v-if="![7,8].includes($store.getters.getCompanyModuleType)">
|
||||
<div class="col">
|
||||
<div class="row m-b-15">
|
||||
<div class="col">
|
||||
<validation-wrapper-component :validator="$v.parameters.reference">
|
||||
<label>Address Reference/Label</label>
|
||||
<input class="form-control" name="reference" v-model="parameters.reference">
|
||||
</validation-wrapper-component>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row m-b-15">
|
||||
<div class="col">
|
||||
<validation-wrapper-component :validator="$v.parameters.street_one">
|
||||
@@ -41,6 +33,14 @@
|
||||
</validation-wrapper-component>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row m-b-15">
|
||||
<div class="col">
|
||||
<validation-wrapper-component :validator="$v.parameters.reference">
|
||||
<label>Address Name / Label</label>
|
||||
<input class="form-control" name="reference" v-model="parameters.reference" placeholder="E.g. Home Address">
|
||||
</validation-wrapper-component>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="row">
|
||||
@@ -59,14 +59,6 @@
|
||||
</validation-wrapper-component>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row m-b-15">
|
||||
<div class="col">
|
||||
<validation-wrapper-component :validator="$v.parameters.remark">
|
||||
<label>Delivery Remark</label>
|
||||
<input class="form-control" name="remark" v-model="parameters.remark">
|
||||
</validation-wrapper-component>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -125,16 +117,70 @@
|
||||
</validation-wrapper-component>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row m-b-15">
|
||||
<div class="col">
|
||||
<validation-wrapper-component :validator="$v.parameters.remark">
|
||||
<label>Remark</label>
|
||||
<input class="form-control" name="remark" v-model="parameters.remark">
|
||||
</validation-wrapper-component>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row m-b-15">
|
||||
<div class="col">
|
||||
<validation-wrapper-component :validator="$v.parameters.remark">
|
||||
<label>Delivery Remark</label>
|
||||
<input class="form-control" name="remark" v-model="parameters.remark">
|
||||
</validation-wrapper-component>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row m-b-15">
|
||||
<div class="col">
|
||||
<validation-wrapper-component selectable :validator="$v.parameters.property_type">
|
||||
<label>房型 Receiver's property type</label>
|
||||
<select-component :options="['住家Landed house', '公寓Condominium (Drop on lobby only)', '工厂Factory', '店面Shop', '商场Shopping Mall (Drop on loading bay only)', 'Others']" v-model="parameters.property_type"></select-component>
|
||||
</validation-wrapper-component>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row m-b-15">
|
||||
<div class="col">
|
||||
<div class="form-group no-margin form-group-default p-b-5">
|
||||
<label>Available to receive goods on: </label>
|
||||
<div class="row">
|
||||
<div class="col-12 col-md pb-3 pb-md-0">
|
||||
<div class="row justify-content-center m-t-10 m-b-10" @click="parameters.receive_goods_working_hours = !parameters.receive_goods_working_hours">
|
||||
<div class="col pointer d-flex justtify-content-center align-items-center">
|
||||
<i class="fa fs-20 fa-fw m-r-5" :class="{'fa-square-o': !parameters.receive_goods_working_hours, 'fa-check-square': parameters.receive_goods_working_hours, 'text-primary':parameters.receive_goods_working_hours}" ></i>
|
||||
<p class="m-b-0">Working Hours (9am-6pm)</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md pb-3 pb-md-0">
|
||||
<div class="row justify-content-center m-t-10 m-b-10" @click="parameters.receive_goods_after_hours = !parameters.receive_goods_after_hours">
|
||||
<div class="col pointer d-flex justtify-content-center align-items-center">
|
||||
<i class="fa fs-20 fa-fw m-r-5" :class="{'fa-square-o': !parameters.receive_goods_after_hours, 'fa-check-square': parameters.receive_goods_after_hours, 'text-primary':parameters.receive_goods_after_hours}" ></i>
|
||||
<p class="m-b-0">After Working Hours</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md pb-3 pb-md-0">
|
||||
<div class="row justify-content-center m-t-10 m-b-10" @click="parameters.receive_goods_on_saturday = !parameters.receive_goods_on_saturday">
|
||||
<div class="col pointer d-flex justtify-content-center align-items-center">
|
||||
<i class="fa fs-20 fa-fw m-r-5" :class="{'fa-square-o': !parameters.receive_goods_on_saturday, 'fa-check-square': parameters.receive_goods_on_saturday, 'text-primary':parameters.receive_goods_on_saturday}" ></i>
|
||||
<p class="m-b-0">On Saturday</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row m-b-15">
|
||||
<div class="col">
|
||||
<validation-wrapper-component :validator="$v.parameters.additional_request">
|
||||
<label>Additional Request</label>
|
||||
<input class="form-control" name="additional_request" v-model="parameters.additional_request">
|
||||
</validation-wrapper-component>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center allign-items-center">
|
||||
<div class="col-12 col-sm-7">
|
||||
<h6 class="text-center fs-12 text-danger">**kindly reply within 2 hours while warehouse contact to arrange for delivery, otherwise, reschedule of delivery date will apply</h6>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="row">
|
||||
@@ -154,7 +200,7 @@
|
||||
props: {
|
||||
id: {
|
||||
type: Number,
|
||||
required: true
|
||||
// required: true
|
||||
},
|
||||
type: {
|
||||
type: Number,
|
||||
@@ -174,6 +220,11 @@
|
||||
remark: '',
|
||||
phone: '',
|
||||
person_in_charge: '',
|
||||
property_type: '',
|
||||
additional_request: '',
|
||||
receive_goods_working_hours: false,
|
||||
receive_goods_after_hours: false,
|
||||
receive_goods_on_saturday: false,
|
||||
}
|
||||
|
||||
}
|
||||
@@ -189,6 +240,11 @@
|
||||
this.parameters.phone = this.data.contact ? this.data.contact.phone : '';
|
||||
this.parameters.person_in_charge = this.data.contact ? this.data.contact.reference : '';
|
||||
this.parameters.remark = this.data.remark ? this.data.remark.content : '';
|
||||
this.parameters.property_type = this.data.property_type ? this.data.property_type : '';
|
||||
this.parameters.additional_request = this.data.additional_request ? this.data.additional_request : '';
|
||||
this.parameters.receive_goods_working_hours = this.data.receive_goods_working_hours ? this.data.receive_goods_working_hours : false;
|
||||
this.parameters.receive_goods_after_hours = this.data.receive_goods_after_hours ? this.data.receive_goods_after_hours : false;
|
||||
this.parameters.receive_goods_on_saturday = this.data.receive_goods_on_saturday ? this.data.receive_goods_on_saturday : false;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
<div class="font-heading all-caps fs-11">{{this.item.name}}</div>
|
||||
<div class="font-heading all-caps fs-11">CIEF/{{this.item.company_module.marking}}</div>
|
||||
</div>
|
||||
<div class="col-auto" v-if="this.item.whatsapp">
|
||||
<div class="font-heading all-caps fs-11">Whatsapp:</div>
|
||||
<div class="font-heading all-caps fs-11">{{ this.item.whatsapp.reference.replace('Whatsapp:', '') }}: {{ this.item.whatsapp.phone }}</div>
|
||||
</div>
|
||||
<div class="col-auto text-center">
|
||||
<div class="font-heading all-caps fs-11">Orders</div>
|
||||
<div class="font-heading all-caps fs-11">{{this.item.order_count}}</div>
|
||||
|
||||
+3
-2
@@ -116,9 +116,10 @@
|
||||
},
|
||||
sumAmount () {
|
||||
var new_object = this.selectedInvoice;
|
||||
return Object.keys(new_object).reduce(function(total, key) {
|
||||
return total + Math.round(new_object[key].amount * 100) / 100;
|
||||
var total = Object.keys(new_object).reduce(function(total, key) {
|
||||
return total + new_object[key].amount;
|
||||
}, 0).toFixed(2);
|
||||
return Math.round(total * 100) / 100;
|
||||
},
|
||||
selectedIds () {
|
||||
return this.selectedInvoice.map(s=>s.id);
|
||||
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
<template>
|
||||
<div class="row bg-white padding-25">
|
||||
<div class="col" v-if="step === 1">
|
||||
<loading-component style="height: 300px; top: 0;" key="1" color="success" v-show="isLoading" ></loading-component>
|
||||
<div class="row justify-content-center" v-show="!isLoading">
|
||||
<div class="col">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>Please provide your Whatsapp phone number:</h3>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="row m-t-20 m-b-15">
|
||||
<div class="col-12">
|
||||
<validation-wrapper-component :validator="$v.parameters.name">
|
||||
<label>Name</label>
|
||||
<input class="form-control" v-model="parameters.name">
|
||||
</validation-wrapper-component>
|
||||
</div>
|
||||
<div class="col-12 p-t-15">
|
||||
<validation-wrapper-component :validator="$v.parameters.phone">
|
||||
<label>Phone</label>
|
||||
<input class="form-control" v-model="parameters.phone">
|
||||
</validation-wrapper-component>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row p-t-15">
|
||||
<div class="col p-r-5">
|
||||
<div class="btn btn-lg block btn m-b-5 no-border bg-master-lighter" data-dismiss="modal">Cancel</div>
|
||||
</div>
|
||||
<div class="col p-l-5">
|
||||
<div class="btn btn-lg block btn m-b-5 no-border text-white bg-primary pointer" @click="nextStep">Confirm</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col" v-if="step === 2">
|
||||
<loading-component style="height: 300px; top: 0;" key="1" color="success" v-show="isLoading" ></loading-component>
|
||||
<div class="row justify-content-center" v-show="!isLoading">
|
||||
<div class="col">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h3>欲知更多详情,请浏览 <a href="https://bit.ly/4a5v34p" target="_blank" class="text-underline">https://bit.ly/4a5v34p</a> 或联系 Whatsapp: <a href="https://wa.me/601136814520" target="_blank" class="text-underline text-success">+6011-36814520</a></h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row p-t-15">
|
||||
<div class="col p-r-5">
|
||||
<div class="btn btn-lg block btn m-b-5 no-border bg-master-lighter" @click="previousStep">Cancel</div>
|
||||
</div>
|
||||
<div class="col p-l-5">
|
||||
<div class="btn btn-lg block btn m-b-5 no-border text-white bg-primary pointer" @click="activateService">Confirm</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { required } from 'vuelidate/lib/validators';
|
||||
import componentHandler from '../../../general/mixins/componentHandler';
|
||||
import modalFormHandler from '../../../general/mixins/modalFormHandler';
|
||||
export default {
|
||||
props: {
|
||||
company:{
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
segmentId:{
|
||||
type: Number,
|
||||
required: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
step: 1,
|
||||
parameters: {
|
||||
name: '',
|
||||
phone: '',
|
||||
}
|
||||
}
|
||||
},
|
||||
validations: {
|
||||
parameters: {
|
||||
name: { required },
|
||||
phone: { required },
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
previousStep() {
|
||||
this.step = 1;
|
||||
},
|
||||
nextStep() {
|
||||
if (this.parameters.name && this.parameters.phone) {
|
||||
this.step = 2;
|
||||
} else {
|
||||
this.parameters = {};
|
||||
this.submit(this.route('api.company.connection.assign', this.company.id, this.company.company_module.connections[0].id), 'post', 'activateService', true, false);
|
||||
}
|
||||
},
|
||||
activateService(){
|
||||
this.parameters.segment_id = this.segmentId
|
||||
|
||||
this.submit(this.route('api.company.connection.assign', this.company.id, this.company.company_module.connections[0].id), 'post', 'activateService', true, false);
|
||||
},
|
||||
successHandler(){
|
||||
location.reload();
|
||||
}
|
||||
},
|
||||
mixins: [componentHandler, modalFormHandler]
|
||||
|
||||
}
|
||||
</script>
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
<template>
|
||||
<div class="row m-t-15 m-b-15 align-items-end parentContainer" v-if="company">
|
||||
<div class="col">
|
||||
<!-- 1688 consent -->
|
||||
<div class="row m-l-0 m-r-0 m-b-15 animate__animated animate__tada animate__repeat-2 animate__delay-3s" v-if="!company.segments.some(item => item.id === 10 || item.id === 11 || item.id === 12)">
|
||||
<div class="col bg-white padding-15">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="row ">
|
||||
<div class="col">
|
||||
<h5 class="m-t-0 text-justify">重磅消息! CIEF 正式开通 <span class="bold">3PL fulfillment 服务</span>!! 你从中国进来的货物, 我们可以直接帮你仓储, 分拣打包, 直接送货到您的顾客手上, 只需系统对接你的 Lazada , Shopee , Tiktok 网店, 就能实现全自动化! 一个月只需 <span class="bold">RMX88</span>! </h5>
|
||||
<h5 class="m-t-0 text-justify">Exciting news! CIEF has officially launched its <span class="bold">3PL fulfillment service</span>! We can assist with warehousing, sorting, packaging, and direct delivery of your goods from China to your customers. Simply integrate your Lazada, Shopee, or TikTok online stores with our system for full automation! Only <span class="bold">RMX88</span> per month!</h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12 text-center">
|
||||
<div class="btn btn-md block btn m-b-5 no-border text-white pointer bg-success requestModal" data-type="fulfilment-interested-now">Interested now (感兴趣)</div>
|
||||
</div>
|
||||
<div class="col-12 text-center">
|
||||
<div class="btn btn-md block btn m-b-5 pointer requestModal" data-type="fulfilment-interested-later">Interested later (感兴趣,但现在不需要)</div>
|
||||
</div>
|
||||
<div class="col-12 text-center">
|
||||
<div class="btn btn-md block btn m-b-5 no-border text-white pointer bg-danger requestModal" data-type="not-interested-confirm">Not interested (不感兴趣)</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<modal-component class="animate__animated animate__fast animate__fadeIn" type="fulfilment-interested-now" styleType="fill-in" size="large">
|
||||
<fulfilment-interested-form-component
|
||||
section="activateService"
|
||||
:company="company"
|
||||
:segmentId="10"
|
||||
>
|
||||
</fulfilment-interested-form-component>
|
||||
</modal-component>
|
||||
<modal-component class="animate__animated animate__fast animate__fadeIn" type="fulfilment-interested-later" styleType="fill-in" size="large">
|
||||
<fulfilment-interested-form-component
|
||||
section="activateService"
|
||||
:company="company"
|
||||
:segmentId="11"
|
||||
>
|
||||
</fulfilment-interested-form-component>
|
||||
</modal-component>
|
||||
<modal-component small type="not-interested-confirm">
|
||||
<div class="row">
|
||||
<div class="col text-center">
|
||||
<div class="row">
|
||||
<div class="col text-center">
|
||||
<div class="row m-b-20">
|
||||
<div class="col">
|
||||
<h5 class="all-caps">Are you Sure?</h5>
|
||||
<div class="fs-11">Are you sure you are not interested in this service?</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col p-r-5">
|
||||
<div data-dismiss="modal" class="btn btn-sm btn-default bg-master-lighter btn-block b-rad-none">No, take me back</div>
|
||||
</div>
|
||||
<div class="col p-l-5">
|
||||
<div data-dismiss="modal" class="btn btn-sm btn-danger btn-block b-rad-none" @click="activateService(12)">Yes, I’m sure</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</modal-component>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import componentHandler from '../../../general/mixins/componentHandler';
|
||||
export default {
|
||||
data(){
|
||||
return {
|
||||
section: 'newServiceList',
|
||||
parameters: {
|
||||
segment_id: ''
|
||||
},
|
||||
expanded: false,
|
||||
failed: false,
|
||||
part: 0,
|
||||
isFetchCompany: false,
|
||||
company: null
|
||||
}
|
||||
},
|
||||
created(){
|
||||
this.fetchCompany();
|
||||
},
|
||||
methods: {
|
||||
fetchCompany(){
|
||||
this.parameters = null;
|
||||
this.isFetchCompany = true;
|
||||
this.submit(route('api.company.show', this.$store.getters.getCompanyId), 'get', this.section, false, false)
|
||||
},
|
||||
activateService(segmentId){
|
||||
this.parameters = {
|
||||
segment_id: segmentId
|
||||
};
|
||||
this.part = 1;
|
||||
this.submit(this.route('api.company.connection.assign', this.company.id, this.company.company_module.connections[0].id), 'post', 'activateService', true, false);
|
||||
},
|
||||
successHandler(response){
|
||||
if (this.isFetchCompany) {
|
||||
this.company = response.payload.data;
|
||||
this.isFetchCompany = false;
|
||||
}
|
||||
if(this.part == 1 || this.part == 4){
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
},
|
||||
mixins: [componentHandler]
|
||||
}
|
||||
</script>
|
||||
@@ -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]
|
||||
}
|
||||
|
||||
+229
@@ -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>
|
||||
@@ -74,9 +74,6 @@
|
||||
data(){
|
||||
return {
|
||||
filters: this.options,
|
||||
pollingInterval: null,
|
||||
isPolling: false,
|
||||
isFetchingResult: false,
|
||||
isLoading: false,
|
||||
}
|
||||
},
|
||||
@@ -87,13 +84,26 @@
|
||||
computed: {
|
||||
pendingList () {
|
||||
return this.$store.getters.isInCompleteQueue(this.section);
|
||||
}
|
||||
},
|
||||
getJob() {
|
||||
return this.$store.getters.getJob(this.section);
|
||||
},
|
||||
getJobAttemptCount() {
|
||||
return this.$store.getters.getJobAttemptCount(this.section);
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
pendingList(inComplete){
|
||||
if(inComplete){
|
||||
this.fetchList();
|
||||
}
|
||||
},
|
||||
getJobAttemptCount(newValue, oldValue) {
|
||||
// console.log('Old value:', JSON.stringify(oldValue));
|
||||
// console.log('New value:', JSON.stringify(newValue));
|
||||
if(this.getJob){
|
||||
this.fetchJobResult(this.getJob.isLastAttempt);
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -101,7 +111,7 @@
|
||||
let listDecorators = this.$store.getters.getListDetails(this.section);
|
||||
let url = this.endpoint + '?page=' + listDecorators.page + '&filters=' + JSON.stringify(listDecorators.filters);
|
||||
this.isLoading = true;
|
||||
this.submitJob(url);
|
||||
this.$store.dispatch('submitJobRequest', {'url': url, 'name': this.section});
|
||||
},
|
||||
successHandler(response){
|
||||
let result = JSON.parse(response.payload.data.result);
|
||||
@@ -118,83 +128,21 @@
|
||||
to: result.meta.to,
|
||||
total: result.meta.total
|
||||
};
|
||||
|
||||
this.stopPolling();
|
||||
this.$store.dispatch('completeList', {'name': this.section, 'data': result.data});
|
||||
this.$store.dispatch('stopPollingJobResultByJobId', {'jobId': this.getJob.jobId});
|
||||
this.$refs.pagination.makePagination(result.meta, result.links);
|
||||
this.isLoading = false;
|
||||
},
|
||||
errorHandler(error){
|
||||
this.isFetchingResult = false;
|
||||
this.isPolling = false;
|
||||
// console.log("Error: " + JSON.stringify(error));
|
||||
this.$store.dispatch('updatePollingJobResultByJobId', {'jobId': this.getJob.jobId, 'isPolling': false, 'isFetchingResult': false });
|
||||
},
|
||||
startPolling(jobId, maxAttempts = 8) {
|
||||
let attempts = 0;
|
||||
let interval = 10000; // Initial interval
|
||||
|
||||
const resetPollingInterval = (customInterval) => {
|
||||
this.pollingInterval = setInterval(pollJobResult, customInterval);
|
||||
};
|
||||
|
||||
const pollJobResult = () => {
|
||||
if (this.isPolling || this.isFetchingResult) {
|
||||
return;
|
||||
}
|
||||
this.isPolling = true;
|
||||
|
||||
attempts++;
|
||||
if(attempts === 1){
|
||||
this.stopPolling();
|
||||
resetPollingInterval(5000);
|
||||
}
|
||||
|
||||
if (attempts > maxAttempts) {
|
||||
this.stopPolling();
|
||||
this.isLoading = false;
|
||||
console.log(`Reached maximum attempts (${maxAttempts}). Polling stopped.`);
|
||||
return;
|
||||
}
|
||||
|
||||
if(attempts === maxAttempts){
|
||||
this.fetchJobResult(jobId, true);
|
||||
}
|
||||
else{
|
||||
this.fetchJobResult(jobId);
|
||||
}
|
||||
};
|
||||
|
||||
// pollJobResult(); // Initial call
|
||||
this.pollingInterval = setInterval(pollJobResult, interval);
|
||||
},
|
||||
stopPolling() {
|
||||
clearInterval(this.pollingInterval);
|
||||
this.pollingInterval = null;
|
||||
this.isPolling = false;
|
||||
this.isFetchingResult = false;
|
||||
},
|
||||
submitJob(url){
|
||||
fetchJobResult(isLastAttempt = false) {
|
||||
this.$store.dispatch('updatePollingJobResultByJobId', {'jobId': this.getJob.jobId, 'isFetchingResult': true });
|
||||
try {
|
||||
this.$store.dispatch('crudRequestV2', {endpoint: url, method: 'get'}).then(response => {
|
||||
let success = response.ok;
|
||||
response.json().then(response => {
|
||||
if(!success){return;}
|
||||
let jobId = response.payload.data.job_id;
|
||||
if(jobId){
|
||||
this.startPolling(jobId);
|
||||
}
|
||||
});
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Error submitJob', error);
|
||||
}
|
||||
},
|
||||
fetchJobResult(jobId, isLastAttempt = false) {
|
||||
// console.log('fetchJobResult: ', jobId);
|
||||
this.isFetchingResult = true;
|
||||
try {
|
||||
let anotherEndpoint = route('api.job.fetch', jobId);
|
||||
let anotherEndpoint = route('api.job.fetch', this.getJob.jobId);
|
||||
if(isLastAttempt){
|
||||
anotherEndpoint = route('api.job.fetch.last.attempt', jobId, isLastAttempt);
|
||||
anotherEndpoint = route('api.job.fetch.last.attempt', this.getJob.jobId, isLastAttempt);
|
||||
}
|
||||
this.poll(anotherEndpoint, 'get', this.section, false, false); //cief todo: Uncaught (in promise) null
|
||||
} catch (error) {
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
<template>
|
||||
<div class="w-100 multi-select-container">
|
||||
<vue-multi-select ref="multiSelect" v-model="localValue" search :options="settings" :btnLabel="btnLabel" :selectOptions="options" class="w-100" style="height: 25px;" @close="close">
|
||||
<template v-slot:option="{ option }">
|
||||
<div class="d-flex justify-content-start align-items-center">
|
||||
<input class="m-l-5 m-r-5" type="checkbox" :checked="option.selected" />
|
||||
<span>{{ option.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</vue-multi-select>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import vueMultiSelect from 'vue-multi-select';
|
||||
import 'vue-multi-select/dist/lib/vue-multi-select.css';
|
||||
import PerfectScrollbar from 'perfect-scrollbar';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
value: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: () => []
|
||||
},
|
||||
options: {
|
||||
type: Array,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
localValue: this.value,
|
||||
settings: {
|
||||
multi: true,
|
||||
groups: false,
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
btnLabel(localValue) {
|
||||
if (localValue.length === 0) {
|
||||
return 'Please select';
|
||||
}
|
||||
return localValue.join(', ');
|
||||
},
|
||||
close() {
|
||||
this.$emit('input', this.localValue);
|
||||
}
|
||||
},
|
||||
components: {
|
||||
vueMultiSelect,
|
||||
PerfectScrollbar,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.multi-select-container .select>button {
|
||||
width: 100%;
|
||||
min-height: unset;
|
||||
}
|
||||
|
||||
.multi-select-container .select .selectItem {
|
||||
color: black !important;
|
||||
}
|
||||
</style>
|
||||
@@ -5,9 +5,10 @@
|
||||
<div class="col-6 no-padding">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<a :href="route('order.qr.download', item.id)" target="_blank">
|
||||
<a :href="route('order.qr.download', item.id)" target="_blank" class="d-flex justify-content-center allign-items-center">
|
||||
<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" style="max-width: 150px; max-height: 150px;">
|
||||
</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">
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<div class="col-auto hide" v-if="$store.getters.isSuperAdmin">
|
||||
<button type="button" class="btn b-rad-none btn-danger fs-11 requestModal" data-type="deletePackingList"><i class="fa fa-times text-white fs-12"></i></button>
|
||||
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="deletePackingList">
|
||||
<delete-packinglist-form-component :data="data"></delete-packinglist-form-component>
|
||||
<delete-packinglist-form-component :data="data" :section="section"></delete-packinglist-form-component>
|
||||
</modal-component>
|
||||
<button type="button" class="btn b-rad-none btn-primary fs-11 requestModal" data-type="claimPackingList">Claim</button>
|
||||
</div>
|
||||
@@ -51,7 +51,7 @@
|
||||
<div class="btn btn-sm btn-success btn-block b-rad-none" data-dismiss="modal">Cancel</div>
|
||||
</div>
|
||||
<div class="col p-l-5">
|
||||
<div class="btn btn-sm btn-danger btn-block b-rad-none" data-dismiss="modal" @click="submit(route('api.packing_list.delete', item.id), 'delete', 'unclaimedPackingListSection', true, true)">Confirm</div>
|
||||
<div class="btn btn-sm btn-danger btn-block b-rad-none" data-dismiss="modal" @click="submit(route('api.packing_list.delete', item.id), 'delete', section, true, true)">Confirm</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -78,6 +78,12 @@
|
||||
<script>
|
||||
import componentHandler from '../../../general/mixins/componentHandler';
|
||||
export default {
|
||||
mixins: [componentHandler]
|
||||
mixins: [componentHandler],
|
||||
data() {
|
||||
return {
|
||||
isLoading: false,
|
||||
section: 'unclaimedPackingListSection',
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -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>
|
||||
|
||||
-322
@@ -1,322 +0,0 @@
|
||||
<template>
|
||||
<div class="row m-b-15 m-l-5 m-r-10 parentContainer">
|
||||
<div class="col bg-white rounded">
|
||||
<div class="row">
|
||||
<div class="col padding-20">
|
||||
<div class="row align-items-center">
|
||||
<div class="col">
|
||||
<p class="no-margin fs-10 all-caps">Marking</p>
|
||||
<div class="no-margin">
|
||||
<div v-if="item.order">
|
||||
<a :href="route('customer.profile', item.order.company_module.marking)">{{item.order.company_module.marking}}</a>/<a :href="route('order.show', item.order.reference)">{{item.order.reference}}</a>
|
||||
<p>{{item.loading_days_ago}}</p>
|
||||
</div>
|
||||
<div v-else class="text-danger">Unclaimed Packing List</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<p class="no-margin fs-10 all-caps">Container</p>
|
||||
<div v-if="item.packages[0].container"> {{item.packages[0].container.container_reference}}</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<p class="no-margin fs-10 all-caps">Invoice Date</p>
|
||||
<div v-if="!item.shipping_transaction">n/a</div>
|
||||
<div v-if="item.shipping_transaction"> {{ item.shipping_transaction.updated_at }}</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div v-if="item.order">
|
||||
<p class="no-margin fs-10 all-caps">Address</p>
|
||||
<div>{{ item.order.address.post_code_area}}</div>
|
||||
<div>{{ item.order.address.district.name +' '+item.order.address.postcode+' '+item.order.address.state.name }}</div>
|
||||
</div>
|
||||
<div v-else class="text-danger">Unclaimed</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<p class="no-margin fs-10 all-caps">Status</p>
|
||||
<div class="all-caps">{{ invoice_status }}</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<p class="no-margin fs-10 all-caps">Amount</p>
|
||||
<div v-if="!item.shipping_transaction">n/a</div>
|
||||
<div v-if="item.shipping_transaction">MYR {{ item.shipping_transaction.amount.toFixed(2) }}</div>
|
||||
</div>
|
||||
<div class="col-auto p-l-0 p-r-0" v-if="['Pending Payment', 'Paid Invoice', 'Suspended Invoice'].includes(invoice_status)">
|
||||
<div v-if="item.shipping_transaction">
|
||||
<div v-if="item.shipping_transaction.documents.length">
|
||||
<div v-for="file in item.shipping_transaction.documents[0].files" v-bind:key="file.id" class="col-auto no-padding">
|
||||
<document-file-viewer-component :file="file">
|
||||
<template slot="button">
|
||||
<div class="btn bg-grey no-border muted">
|
||||
<i class="fa fa-file-pdf-o"></i>
|
||||
</div>
|
||||
</template>
|
||||
</document-file-viewer-component>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="btn bg-grey no-border muted invisible">
|
||||
<i class="fa fa-file-pdf-o"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div class="row text-center parentContainer m-b-10" v-if="['Pending Invoice'].includes(invoice_status) && !item.receive_packing_list" >
|
||||
<div class="col">
|
||||
<div class="requestModal pointer btn btn-primary btn-xs" data-type="addWarehouseTransport">
|
||||
Add Warehouse Transport
|
||||
</div>
|
||||
<modal-component class="animate_animated animatefast animate_fadeIn" styleType="fill-in" type="addWarehouseTransport">
|
||||
<create-warehouse-transport-form-component :packinglistId="item.id" :section="section"></create-warehouse-transport-form-component>
|
||||
</modal-component>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="btn bg-grey no-border" @click="expanded = !expanded" v-if="['Pending Approval', 'Pending Payment'].includes(invoice_status)">
|
||||
<i class="fa" :class="{'fa-angle-down': !expanded, 'fa-angle-up': expanded}" ></i>
|
||||
</div>
|
||||
<div v-if="!item.shipping_transaction">
|
||||
<div v-if="item.order">
|
||||
<div v-if="!item.order.company_module.billingAddress">
|
||||
<div class="btn btn-primary btn-xs pointer requestModal btn-block" data-type="billingAddressComponent">Add Billing Address</div>
|
||||
<modal-component class="animate__animated animate__fast animate__fadeIn" size="extra-large" styleType="fill-in" type="billingAddressComponent">
|
||||
<address-form-component :id="item.order.company_module.id" :section="section" :type=1></address-form-component>
|
||||
</modal-component>
|
||||
</div>
|
||||
<div class="row" v-if="item.order.company_module.billingAddress">
|
||||
<div class="col">
|
||||
<div class="col-auto requestModal pointer" data-type="editBillingAddress">
|
||||
<i class="fa fa-edit pointer fa-fw m-l-5"></i> Edit billing Address
|
||||
</div>
|
||||
<modal-component class="animate__animated animate__fast animate__fadeIn" size="extra-large" styleType="fill-in" type="editBillingAddress">
|
||||
<div class="row">
|
||||
<div class="col bg-white">
|
||||
<address-form-component :id="item.order.company_module.id" :data="item.order.company_module.billingAddress" section="editBillingAddress"></address-form-component>
|
||||
</div>
|
||||
</div>
|
||||
</modal-component>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!item.order.address.post_code_area">
|
||||
<div class="btn btn-xs btn-primary pointer m-t-10 requestModal btn-block" data-type="defineLocation">Define Location</div>
|
||||
<modal-component class="animate_animated animatefast animate_fadeIn" styleType="fill-in" type="defineLocation">
|
||||
<declare-postcode-area-form-component :data="item.order.address" :section="section"></declare-postcode-area-form-component>
|
||||
</modal-component>
|
||||
</div>
|
||||
<div v-if="item.order.company_module.billingAddress && item.order.address.post_code_area" class="btn btn-outline-primary btn-lg pointer" @click="generateInvoice()">Generate Invoice</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="btn btn-outline-primary btn-lg pointer invisible">Generate Invoice</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn bg-grey no-border muted requestModal" v-if="item.shipping_transaction && invoice_status == 'Pending Approval'" data-type="confirmInvoice">
|
||||
<i class="fa fa-check fs-12"></i>
|
||||
</div>
|
||||
<div class="btn bg-grey no-border muted requestModal" v-if="item.shipping_transaction && invoice_status == 'Pending Approval'" data-type="deleteInoive">
|
||||
<i class="fa fa-close fs-12"></i>
|
||||
</div>
|
||||
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="confirmInvoice">
|
||||
<approve-shipping-invoice-form-component :section="section" :data="data"></approve-shipping-invoice-form-component>
|
||||
</modal-component>
|
||||
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="deleteInoive">
|
||||
<delete-shipping-invoice-form-component :section="section" :data="data"></delete-shipping-invoice-form-component>
|
||||
</modal-component>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row b-t b-grey p-t-10 m-l-5 m-r-5" v-show="expanded" v-if="item.shipping_transaction && ['Pending Approval', 'Suspended Invoice'].includes(invoice_status)">
|
||||
<div class="col p-b-10">
|
||||
<div class="row">
|
||||
<div class="col p-l-20 p-r-20 p-t-10 p-b-10">
|
||||
<div class="row align-items-center">
|
||||
<div class="col">
|
||||
<p class="no-margin fs-10 all-caps">Container Reference</p>
|
||||
<div v-if="item.packages.length">{{ item.packages[0].container ? item.packages[0].container.container_reference : 'n/a' }}</div>
|
||||
<div v-else>n/a</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<p class="no-margin fs-10 all-caps">Due Date</p>
|
||||
<div v-if="item.packages.length">
|
||||
<div v-if="item.packages[0].container">
|
||||
<div v-if="item.packages[0].container.transport">{{ item.packages[0].container.transport.drop_date == null ? item.packages[0].container.transport.current_schedule.etd : item.packages[0].container.transport.drop_date }}</div>
|
||||
<div v-else>n/a</div>
|
||||
</div>
|
||||
<div v-else>n/a</div>
|
||||
</div>
|
||||
<div v-else>n/a</div>
|
||||
</div>
|
||||
<!-- <div class="col">
|
||||
<p class="no-margin fs-10 all-caps">Paid Date</p>
|
||||
<div>n/a</div>
|
||||
</div> -->
|
||||
<div class="col">
|
||||
<p class="no-margin fs-10 all-caps">Total CBM</p>
|
||||
<div>{{ (parseFloat(cbm) + parseFloat(overweight)).toFixed(3) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h5 class="text-underline text-center">Invoice Details</h5>
|
||||
<invoice-items-form-component :data="item.shipping_transaction" :section="section"></invoice-items-form-component>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<p class="no-margin fs-10 all-caps">Subtotal</p>
|
||||
<div>{{ item.shipping_transaction.amount - item.shipping_transaction.service_charge - item.shipping_transaction.tax }}</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<p class="no-margin fs-10 all-caps">Service Charges</p>
|
||||
<div>{{ item.shipping_transaction.service_charge }}</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<p class="no-margin fs-10 all-caps">Tax</p>
|
||||
<div>{{ item.shipping_transaction.tax }}</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<p class="no-margin fs-10 all-caps">Total</p>
|
||||
<div>{{ item.shipping_transaction.amount }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row b-t b-grey p-t-10 m-l-5 m-r-5" v-show="expanded" v-if="item.shipping_transaction && invoice_status == 'Pending Payment'">
|
||||
<div class="col-12 col-md-7 padding-20">
|
||||
<div class="row bg-master-lightest h-100">
|
||||
<div class="col">
|
||||
<div class="row bg-master-lightest" v-if="item.shipping_transaction.payment_attempts.length">
|
||||
<div class="col">
|
||||
<div class="row m-t-10 m-b-10">
|
||||
<div class="col">
|
||||
<div class="font-head fs-10 all-caps">Payment Attempt</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<shipping-transaction-component v-for="item in item.shipping_transaction.payment_attempts" v-bind:key="item.id" :data="item" ></shipping-transaction-component>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row bg-master-lightest" v-if="item.shipping_transaction.payment_history.length">
|
||||
<div class="col">
|
||||
<div class="row m-t-10 m-b-10">
|
||||
<div class="col">
|
||||
<div class="font-head fs-10 all-caps">Payment History</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<payment-history-component v-for="item in item.shipping_transaction.payment_history" v-bind:key="item.id" :data="item" ></payment-history-component>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-5 padding-20 parentContainer">
|
||||
<div class="row bg-master-lightest h-100">
|
||||
<div class="col">
|
||||
<div class="row padding-10">
|
||||
<div class="col">
|
||||
<div class="row align-items-end m-b-10 text-complete">
|
||||
<div class="col">
|
||||
<div class="font-heading all-caps fs-12">Total Amount:</div>
|
||||
</div>
|
||||
<div class="col-auto text-right">
|
||||
<div class="font-heading fs-12">MYR {{(Math.round((item.shipping_transaction.amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row align-items-end m-b-10 text-success hide">
|
||||
<div class="col">
|
||||
<div class="font-heading all-caps fs-12">Paid Total:</div>
|
||||
</div>
|
||||
<div class="col-auto text-right">
|
||||
<!-- <div class="font-heading fs-12">MYR {{(Math.round((item.shipping_transaction.paid_amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}</div> -->
|
||||
<div class="font-heading fs-12">Paid Total</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row align-items-end m-b-10 hide">
|
||||
<div class="col">
|
||||
<div class="font-heading all-caps fs-12">Floating Amount:</div>
|
||||
</div>
|
||||
<div class="col-auto text-right">
|
||||
<!-- <div class="font-heading fs-12">MYR {{(Math.round((item.shipping_transaction.floating_amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}</div> -->
|
||||
<div class="font-heading fs-12">Floating Amount</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row align-items-end bold text-danger">
|
||||
<div class="col">
|
||||
<div class="font-heading all-caps fs-12">OutStanding Total:</div>
|
||||
</div>
|
||||
<div class="col-auto text-right">
|
||||
<div class="font-heading fs-12">MYR {{(Math.round((item.shipping_transaction.outstanding + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row m-t-20" v-if="item.shipping_transaction.outstanding > 0">
|
||||
<div class="col">
|
||||
<div class="btn btn-sm all-caps b-rad-none btn-success btn-block requestModal" data-type="makePayment">Make Payment</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="makePayment">
|
||||
<payment-form-component :data="item.shipping_transaction" :section="section"></payment-form-component>
|
||||
</modal-component>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import componentHandler from '../../../general/mixins/componentHandler';
|
||||
export default {
|
||||
props: {
|
||||
invoice_status: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
section:{
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data(){
|
||||
return {
|
||||
parameters: {
|
||||
packing_list_id: null,
|
||||
transaction_details: [],
|
||||
},
|
||||
expanded: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
cbm () {
|
||||
return (Math.ceil((this.item.packages.reduce((total, obj) => (obj.type === 2 ? 0 : obj.cbm) + total, 0)) * 1000) / 1000).toFixed(3)
|
||||
},
|
||||
overweight(){
|
||||
return (Math.ceil((this.item.packages.reduce((total, obj) => (obj.type === 2 ? obj.cbm : 0) + total, 0)) * 1000) / 1000).toFixed(3)
|
||||
}
|
||||
},
|
||||
created(){
|
||||
this.parameters.packing_list_id = this.data.id;
|
||||
},
|
||||
methods: {
|
||||
generateInvoice() {
|
||||
this.submit(this.route('api.transaction.invoice.create'), 'post', this.section, true, true);
|
||||
},
|
||||
successHandler(response){
|
||||
this.item = response.payload.data;
|
||||
this.updateList();
|
||||
}
|
||||
},
|
||||
mixins: [componentHandler]
|
||||
}
|
||||
</script>
|
||||
+1
@@ -38,6 +38,7 @@
|
||||
<template slot="list" slot-scope="{data}">
|
||||
<single-parent-admin-payments-billing-component :data="data" :invoice_status="invoice_status" :section="section" ></single-parent-admin-payments-billing-component>
|
||||
<!-- <admin-payments-billing-component :data="data" :invoice_status="invoice_status" :section="section" ></admin-payments-billing-component> -->
|
||||
<!-- AdminPaymentsBillingComponent.vue deleted to avoid confusion -->
|
||||
</template>
|
||||
</list-component>
|
||||
</div>
|
||||
|
||||
+26
-5
@@ -68,10 +68,10 @@
|
||||
<i class="fa fa-repeat"></i>
|
||||
</span>
|
||||
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="regenerateInvoice">
|
||||
<general-confirmation-form-component
|
||||
contentText="Are you sure you want to regenerate this Invoice?"
|
||||
modalType="delete"
|
||||
buttonText="Regenerate"
|
||||
<general-confirmation-form-component
|
||||
contentText="Are you sure you want to regenerate this Invoice?"
|
||||
modalType="delete"
|
||||
buttonText="Regenerate"
|
||||
class="text-center"
|
||||
:apiRoute="route('api.transaction.invoice.regenerate', item.id)"
|
||||
apiMethod="post"
|
||||
@@ -93,6 +93,16 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" v-if="$store.getters.isAdmin">
|
||||
<div class="col padding-20">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<p class="no-margin fs-10 all-caps">Packinglist Reference</p>
|
||||
<div>{{ item.packing_list_reference }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row b-t b-grey p-t-10 m-l-5 m-r-5" v-show="expanded" v-if="![5, 6].includes(item.status)">
|
||||
<div class="col-12 col-md-7 padding-20">
|
||||
<div class="row bg-master-lightest h-100">
|
||||
@@ -179,7 +189,7 @@
|
||||
<div class="font-heading fs-12">MYR {{(Math.round((item.outstanding + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row m-t-20" v-if="item.outstanding - item.floating > 0.009">
|
||||
<div class="row m-t-20" v-if="item.outstanding - item.floating > 0.009 && !paymentPending">
|
||||
<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">
|
||||
@@ -238,6 +248,17 @@
|
||||
latestComment() {
|
||||
let questions = this.item.remarks;
|
||||
return questions.slice().reverse()[0];
|
||||
},
|
||||
paymentPending(){
|
||||
if (Array.isArray(this.item.transactions)) {
|
||||
for (let i = 0; i < this.item.transactions.length; i++) {
|
||||
const status = this.item.transactions[i].status;
|
||||
if (status === 1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},
|
||||
created(){
|
||||
|
||||
+17
-2
@@ -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)
|
||||
|
||||
+19
-2
@@ -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>
|
||||
|
||||
+7
-1
@@ -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>
|
||||
|
||||
+42
-4
@@ -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">
|
||||
@@ -92,6 +92,22 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row bg-white padding-5" v-if="$store.getters.isSuperAdmin">
|
||||
<div class="col-auto">
|
||||
<div class="font-heading fs-8 muted all-caps">Payment Method</div>
|
||||
<div class="font-heading fs-10">
|
||||
{{ convertPaymentMethodToText(item.payment_method) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div class="font-heading fs-8 muted all-caps">Created At</div>
|
||||
<div class="font-heading fs-10">{{ item.created_at }}</div>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div class="font-heading fs-8 muted all-caps">Updated At</div>
|
||||
<div class="font-heading fs-10">{{ item.updated_at }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row b-t b-grey" v-if="expandPaymentDetails">
|
||||
<div class="col bg-white padding-15">
|
||||
<!-- <div class="row align-items-end m-b-10 text-success bold">
|
||||
@@ -157,6 +173,13 @@
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="row no-margin" v-if="item.payment_method === 4 && item.payment_reference">
|
||||
<a :href="route('billplz.bill', item.payment_reference)" target="_blank">
|
||||
<div class="icon-thumbnail fs-11 text-white icon-25 bg-primary btn-rounded float-left m-r-5">
|
||||
<i class="fa fa-file-image-o fs-10"></i>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -181,12 +204,27 @@
|
||||
},
|
||||
methods: {
|
||||
clickExpand(){
|
||||
if(this.item
|
||||
&& ((this.item.payment_method !== 5 && this. item.documents.length)
|
||||
|| (this.item.payment_method === 5 && (this.item.status === 2 || this.item.status === 3)))){
|
||||
// if(this.item
|
||||
// && ((this.item.payment_method !== 5 && this. item.documents.length)
|
||||
// || (this.item.payment_method === 5 && (this.item.status === 2 || this.item.status === 3)))){
|
||||
// this.expandPaymentDetails = !this.expandPaymentDetails;
|
||||
// }
|
||||
|
||||
if(this.item){
|
||||
this.expandPaymentDetails = !this.expandPaymentDetails;
|
||||
}
|
||||
},
|
||||
convertPaymentMethodToText(number) {
|
||||
var paymentMethods = {
|
||||
1: "CASH",
|
||||
2: "CHEQUE",
|
||||
3: "BA",
|
||||
4: "WALLET",
|
||||
5: "PAYMENT_GATEWAY"
|
||||
};
|
||||
|
||||
return paymentMethods[number] || "Unknown Payment Method";
|
||||
},
|
||||
},
|
||||
mixins: [componentHandler]
|
||||
}
|
||||
|
||||
-322
@@ -1,322 +0,0 @@
|
||||
<template>
|
||||
<div class="row m-b-15 m-l-5 m-r-10 parentContainer">
|
||||
<div class="col bg-white rounded">
|
||||
<div class="row">
|
||||
<div class="col padding-20">
|
||||
<div class="row align-items-center">
|
||||
<div class="col">
|
||||
<p class="no-margin fs-10 all-caps">Marking</p>
|
||||
<div class="no-margin">
|
||||
<div v-if="item.order">
|
||||
<a :href="route('customer.profile', item.order.company_module.marking)">{{item.order.company_module.marking}}</a>/<a :href="route('order.show', item.order.reference)">{{item.order.reference}}</a>
|
||||
<p>{{item.loading_days_ago}}</p>
|
||||
</div>
|
||||
<div v-else class="text-danger">Unclaimed Packing List</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<p class="no-margin fs-10 all-caps">Container</p>
|
||||
<div v-if="item.container"> {{item.container.container_reference}}</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<p class="no-margin fs-10 all-caps">Invoice Date</p>
|
||||
<div v-if="!item.shipping_transaction">n/a</div>
|
||||
<div v-if="item.shipping_transaction"> {{ item.shipping_transaction.updated_at }}</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div v-if="item.order">
|
||||
<p class="no-margin fs-10 all-caps">Address</p>
|
||||
<div>{{ item.order.address.post_code_area}}</div>
|
||||
<div>{{ item.order.address.district.name +' '+item.order.address.postcode+' '+item.order.address.state.name }}</div>
|
||||
</div>
|
||||
<div v-else class="text-danger">Unclaimed</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<p class="no-margin fs-10 all-caps">Status</p>
|
||||
<div class="all-caps">{{ invoice_status }}</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<p class="no-margin fs-10 all-caps">Amount</p>
|
||||
<div v-if="!item.shipping_transaction">n/a</div>
|
||||
<div v-if="item.shipping_transaction">MYR {{ item.shipping_transaction.amount.toFixed(2) }}</div>
|
||||
</div>
|
||||
<div class="col-auto p-l-0 p-r-0" v-if="['Pending Payment', 'Paid Invoice', 'Suspended Invoice'].includes(invoice_status)">
|
||||
<div v-if="item.shipping_transaction">
|
||||
<div v-if="item.shipping_transaction.documents.length">
|
||||
<div v-for="file in item.shipping_transaction.documents[0].files" v-bind:key="file.id" class="col-auto no-padding">
|
||||
<document-file-viewer-component :file="file">
|
||||
<template slot="button">
|
||||
<div class="btn bg-grey no-border muted">
|
||||
<i class="fa fa-file-pdf-o"></i>
|
||||
</div>
|
||||
</template>
|
||||
</document-file-viewer-component>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="btn bg-grey no-border muted invisible">
|
||||
<i class="fa fa-file-pdf-o"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div class="row text-center parentContainer m-b-10" v-if="['Pending Invoice'].includes(invoice_status) && !item.receive_packing_list" >
|
||||
<div class="col">
|
||||
<div class="requestModal pointer btn btn-primary btn-xs" data-type="addWarehouseTransport">
|
||||
Add Warehouse Transport
|
||||
</div>
|
||||
<modal-component class="animate_animated animatefast animate_fadeIn" styleType="fill-in" type="addWarehouseTransport">
|
||||
<create-warehouse-transport-form-component :packinglistId="item.id" :section="section"></create-warehouse-transport-form-component>
|
||||
</modal-component>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="btn bg-grey no-border" @click="expanded = !expanded" v-if="['Pending Approval', 'Pending Payment'].includes(invoice_status)">
|
||||
<i class="fa" :class="{'fa-angle-down': !expanded, 'fa-angle-up': expanded}" ></i>
|
||||
</div>
|
||||
<div v-if="!item.shipping_transaction">
|
||||
<div v-if="item.order">
|
||||
<div v-if="!item.order.company_module.billingAddress">
|
||||
<div class="btn btn-primary btn-xs pointer requestModal btn-block" data-type="billingAddressComponent">Add Billing Address</div>
|
||||
<modal-component class="animate__animated animate__fast animate__fadeIn" size="extra-large" styleType="fill-in" type="billingAddressComponent">
|
||||
<address-form-component :id="item.order.company_module.id" :section="section" :type=1></address-form-component>
|
||||
</modal-component>
|
||||
</div>
|
||||
<div class="row" v-if="item.order.company_module.billingAddress">
|
||||
<div class="col">
|
||||
<div class="col-auto requestModal pointer" data-type="editBillingAddress">
|
||||
<i class="fa fa-edit pointer fa-fw m-l-5"></i> Edit billing Address
|
||||
</div>
|
||||
<modal-component class="animate__animated animate__fast animate__fadeIn" size="extra-large" styleType="fill-in" type="editBillingAddress">
|
||||
<div class="row">
|
||||
<div class="col bg-white">
|
||||
<address-form-component :id="item.order.company_module.id" :data="item.order.company_module.billingAddress" section="editBillingAddress"></address-form-component>
|
||||
</div>
|
||||
</div>
|
||||
</modal-component>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!item.order.address.post_code_area">
|
||||
<div class="btn btn-xs btn-primary pointer m-t-10 requestModal btn-block" data-type="defineLocation">Define Location</div>
|
||||
<modal-component class="animate_animated animatefast animate_fadeIn" styleType="fill-in" type="defineLocation">
|
||||
<declare-postcode-area-form-component :data="item.order.address" :section="section"></declare-postcode-area-form-component>
|
||||
</modal-component>
|
||||
</div>
|
||||
<div v-if="item.order.company_module.billingAddress && item.order.address.post_code_area" class="btn btn-outline-primary btn-lg pointer" @click="generateInvoice()">Generate Invoice</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="btn btn-outline-primary btn-lg pointer invisible">Generate Invoice</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn bg-grey no-border muted requestModal" v-if="item.shipping_transaction && invoice_status == 'Pending Approval'" data-type="confirmInvoice">
|
||||
<i class="fa fa-check fs-12"></i>
|
||||
</div>
|
||||
<div class="btn bg-grey no-border muted requestModal" v-if="item.shipping_transaction && invoice_status == 'Pending Approval'" data-type="deleteInoive">
|
||||
<i class="fa fa-close fs-12"></i>
|
||||
</div>
|
||||
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="confirmInvoice">
|
||||
<approve-shipping-invoice-form-component :section="section" :data="data"></approve-shipping-invoice-form-component>
|
||||
</modal-component>
|
||||
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="deleteInoive">
|
||||
<delete-shipping-invoice-form-component :section="section" :data="data"></delete-shipping-invoice-form-component>
|
||||
</modal-component>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row b-t b-grey p-t-10 m-l-5 m-r-5" v-show="expanded" v-if="item.shipping_transaction && ['Pending Approval', 'Suspended Invoice'].includes(invoice_status)">
|
||||
<div class="col p-b-10">
|
||||
<div class="row">
|
||||
<div class="col p-l-20 p-r-20 p-t-10 p-b-10">
|
||||
<div class="row align-items-center">
|
||||
<div class="col">
|
||||
<p class="no-margin fs-10 all-caps">Container Reference</p>
|
||||
<div v-if="item.packages.length">{{ item.container ? item.container.container_reference : 'n/a' }}</div>
|
||||
<div v-else>n/a</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<p class="no-margin fs-10 all-caps">Due Date</p>
|
||||
<div v-if="item.packages.length">
|
||||
<div v-if="item.container">
|
||||
<div v-if="item.container.transport">{{ item.container.transport.drop_date == null ? item.container.transport.current_schedule.etd : item.container.transport.drop_date }}</div>
|
||||
<div v-else>n/a</div>
|
||||
</div>
|
||||
<div v-else>n/a</div>
|
||||
</div>
|
||||
<div v-else>n/a</div>
|
||||
</div>
|
||||
<!-- <div class="col">
|
||||
<p class="no-margin fs-10 all-caps">Paid Date</p>
|
||||
<div>n/a</div>
|
||||
</div> -->
|
||||
<div class="col">
|
||||
<p class="no-margin fs-10 all-caps">Total CBM</p>
|
||||
<div>{{ (parseFloat(cbm) + parseFloat(overweight)).toFixed(3) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h5 class="text-underline text-center">Invoice Details</h5>
|
||||
<invoice-items-form-component :data="item.shipping_transaction" :section="section"></invoice-items-form-component>
|
||||
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<p class="no-margin fs-10 all-caps">Subtotal</p>
|
||||
<div>{{ item.shipping_transaction.amount - item.shipping_transaction.service_charge - item.shipping_transaction.tax }}</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<p class="no-margin fs-10 all-caps">Service Charges</p>
|
||||
<div>{{ item.shipping_transaction.service_charge }}</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<p class="no-margin fs-10 all-caps">Tax</p>
|
||||
<div>{{ item.shipping_transaction.tax }}</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<p class="no-margin fs-10 all-caps">Total</p>
|
||||
<div>{{ item.shipping_transaction.amount }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row b-t b-grey p-t-10 m-l-5 m-r-5" v-show="expanded" v-if="item.shipping_transaction && invoice_status == 'Pending Payment'">
|
||||
<div class="col-12 col-md-7 padding-20">
|
||||
<div class="row bg-master-lightest h-100">
|
||||
<div class="col">
|
||||
<div class="row bg-master-lightest" v-if="item.shipping_transaction.payment_attempts.length">
|
||||
<div class="col">
|
||||
<div class="row m-t-10 m-b-10">
|
||||
<div class="col">
|
||||
<div class="font-head fs-10 all-caps">Payment Attempt</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<shipping-transaction-component v-for="item in item.shipping_transaction.payment_attempts" v-bind:key="item.id" :data="item" ></shipping-transaction-component>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row bg-master-lightest" v-if="item.shipping_transaction.payment_history.length">
|
||||
<div class="col">
|
||||
<div class="row m-t-10 m-b-10">
|
||||
<div class="col">
|
||||
<div class="font-head fs-10 all-caps">Payment History</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<payment-history-component v-for="item in item.shipping_transaction.payment_history" v-bind:key="item.id" :data="item" ></payment-history-component>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-5 padding-20 parentContainer">
|
||||
<div class="row bg-master-lightest h-100">
|
||||
<div class="col">
|
||||
<div class="row padding-10">
|
||||
<div class="col">
|
||||
<div class="row align-items-end m-b-10 text-complete">
|
||||
<div class="col">
|
||||
<div class="font-heading all-caps fs-12">Total Amount:</div>
|
||||
</div>
|
||||
<div class="col-auto text-right">
|
||||
<div class="font-heading fs-12">MYR {{(Math.round((item.shipping_transaction.amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row align-items-end m-b-10 text-success hide">
|
||||
<div class="col">
|
||||
<div class="font-heading all-caps fs-12">Paid Total:</div>
|
||||
</div>
|
||||
<div class="col-auto text-right">
|
||||
<!-- <div class="font-heading fs-12">MYR {{(Math.round((item.shipping_transaction.paid_amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}</div> -->
|
||||
<div class="font-heading fs-12">Paid Total</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row align-items-end m-b-10 hide">
|
||||
<div class="col">
|
||||
<div class="font-heading all-caps fs-12">Floating Amount:</div>
|
||||
</div>
|
||||
<div class="col-auto text-right">
|
||||
<!-- <div class="font-heading fs-12">MYR {{(Math.round((item.shipping_transaction.floating_amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}</div> -->
|
||||
<div class="font-heading fs-12">Floating Amount</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row align-items-end bold text-danger">
|
||||
<div class="col">
|
||||
<div class="font-heading all-caps fs-12">OutStanding Total:</div>
|
||||
</div>
|
||||
<div class="col-auto text-right">
|
||||
<div class="font-heading fs-12">MYR {{(Math.round((item.shipping_transaction.outstanding + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row m-t-20" v-if="item.shipping_transaction.outstanding > 0">
|
||||
<div class="col">
|
||||
<div class="btn btn-sm all-caps b-rad-none btn-success btn-block requestModal" data-type="makePayment">Make Payment</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="makePayment">
|
||||
<payment-form-component :data="item.shipping_transaction" :section="section"></payment-form-component>
|
||||
</modal-component>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import componentHandler from '../../../general/mixins/componentHandler';
|
||||
export default {
|
||||
props: {
|
||||
invoice_status: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
section:{
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data(){
|
||||
return {
|
||||
parameters: {
|
||||
packing_list_id: null,
|
||||
transaction_details: [],
|
||||
},
|
||||
expanded: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
cbm () {
|
||||
return (Math.ceil((this.item.packages.reduce((total, obj) => (obj.type === 2 ? 0 : obj.cbm) + total, 0)) * 1000) / 1000).toFixed(3)
|
||||
},
|
||||
overweight(){
|
||||
return (Math.ceil((this.item.packages.reduce((total, obj) => (obj.type === 2 ? obj.cbm : 0) + total, 0)) * 1000) / 1000).toFixed(3)
|
||||
}
|
||||
},
|
||||
created(){
|
||||
this.parameters.packing_list_id = this.data.id;
|
||||
},
|
||||
methods: {
|
||||
generateInvoice() {
|
||||
this.submit(this.route('api.transaction.invoice.create'), 'post', this.section, true, true);
|
||||
},
|
||||
successHandler(response){
|
||||
this.item = response.payload.data;
|
||||
this.updateList();
|
||||
}
|
||||
},
|
||||
mixins: [componentHandler]
|
||||
}
|
||||
</script>
|
||||
+5
-5
@@ -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">
|
||||
|
||||
@@ -37,7 +37,11 @@
|
||||
<div class="row" v-if="isEdit">
|
||||
<div class="col padding-25 bg-master-lightest">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="col" v-if="name">
|
||||
<p class="m-b-0 small muted">Name</p>
|
||||
<p class="m-b-0 bold">{{product.name}}</p>
|
||||
</div>
|
||||
<div class="col" v-else>
|
||||
<validation-wrapper-component :validator="$v.product.name">
|
||||
<label>Name</label>
|
||||
<input class="form-control" v-model="product.name">
|
||||
@@ -93,6 +97,10 @@
|
||||
// required: true
|
||||
default: 0
|
||||
},
|
||||
name:{
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
},
|
||||
data(){
|
||||
return {
|
||||
@@ -102,6 +110,7 @@
|
||||
quantity: 0,
|
||||
price: 0,
|
||||
amount: 0,
|
||||
reference: 'CUSTOM_CHARGES',
|
||||
},
|
||||
products: []
|
||||
}
|
||||
@@ -113,6 +122,12 @@
|
||||
price: { required },
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if(this.name){
|
||||
this.product.name = this.name;
|
||||
this.product.reference = 'PAY_ON_BEHALF';
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (this.data) {
|
||||
this.product = this.data;
|
||||
@@ -136,7 +151,7 @@
|
||||
this.$emit('add', {
|
||||
name: this.product.name,
|
||||
quantity: this.product.quantity,
|
||||
reference: 'CUSTOM_CHARGES',
|
||||
reference: this.product.reference,
|
||||
price: parseFloat((this.product.price).toString().replace(',', '')),
|
||||
amount: this.productTotal
|
||||
});
|
||||
|
||||
@@ -15,13 +15,14 @@
|
||||
|
||||
<div class="row" v-if="addCharges">
|
||||
<div class="col">
|
||||
<invoice-item-form-component currency="MYR" :editable="!submitted" :section="section" @change="addCharges = !addCharges" @add="addProduct($event)" v-on:remove="removeProduct(index)"></invoice-item-form-component>
|
||||
<invoice-item-form-component currency="MYR" :editable="!submitted" :section="section" :name="addChargesName" @change="addCharges = !addCharges" @add="addProduct($event)" v-on:remove="removeProduct(index)"></invoice-item-form-component>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row d-flex justify-content-center allign-items-between align-items-center m-b-15">
|
||||
<div class="col-auto">
|
||||
<div class="btn btn-outline-primary btn-md" @click="addCharges = !addCharges">{{ addCharges? 'Cancel' : 'Add Charges' }}</div>
|
||||
<div class="btn btn-outline-primary btn-md" @click="addCharges = !addCharges; addChargesName = 'Pay On Behalf'">{{ addCharges? 'Cancel' : 'Add \'Pay On Behalf \' Charges' }}</div>
|
||||
<div class="btn btn-outline-primary btn-md" @click="addCharges = !addCharges; addChargesName = ''">{{ addCharges? 'Cancel' : 'Add Charges' }}</div>
|
||||
<div class="btn btn-outline-primary btn-md" @click="submitForm()">Save Change</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -44,6 +45,7 @@
|
||||
parameters: {
|
||||
transaction_details: []
|
||||
},
|
||||
addChargesName: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
@@ -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">
|
||||
@@ -157,6 +157,7 @@
|
||||
this.error = response.payload.data.message;
|
||||
}
|
||||
else{
|
||||
this.closeModal();
|
||||
this.updateList();
|
||||
}
|
||||
}
|
||||
|
||||
+7
-2
@@ -76,9 +76,14 @@
|
||||
files: this.files
|
||||
};
|
||||
this.submit(this.route('api.transaction.payment.verification.create', this.data.id), 'post', this.section, true, true)
|
||||
}
|
||||
},
|
||||
successHandler(response){
|
||||
this.closeModal();
|
||||
this.formHandler();
|
||||
window.location.reload();
|
||||
},
|
||||
},
|
||||
mixins: [ModalFromHandler]
|
||||
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
||||
+1
-1
@@ -113,7 +113,7 @@
|
||||
<div class="row tabsContainer tabContent hide" tab-name="pendingPayment" v-if="isActiveTab('pendingPayment') || showTabContent('pendingPayment')">
|
||||
<div class="col">
|
||||
<payment-filter-component :endpoint="route('api.packing_list.list')" :data="data"></payment-filter-component>
|
||||
<admin-payments-billing-with-search-component :options="{has_invoice_status_in: [2], packing_list_ordered_by_invoice_date: true, per_page: 5, check_for_storage_invoice: 1}" section="pendingPaymentSection" invoice_status="Pending Payment" :with_export="true"></admin-payments-billing-with-search-component>
|
||||
<admin-payments-billing-with-search-component :options="{has_invoice_status_in: [2], packing_list_limit_one_by_type_ordered_by_invoice_date: true, per_page: 5, check_for_storage_invoice: 1}" section="pendingPaymentSection" invoice_status="Pending Payment" :with_export="true"></admin-payments-billing-with-search-component>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row tabsContainer tabContent hide" tab-name="paidInvoice" v-if="isActiveTab('paidInvoice') || showTabContent('paidInvoice')">
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
<template>
|
||||
<div class="w-100">
|
||||
<validation-wrapper-component
|
||||
selectable
|
||||
:validator="$v.parameters.id"
|
||||
>
|
||||
<label>Segment</label>
|
||||
<selectable-component
|
||||
:endpoint="
|
||||
route('api.segment.list')
|
||||
"
|
||||
:section="section"
|
||||
:value="3"
|
||||
valueColumn="id"
|
||||
:labelColumn="['name']"
|
||||
v-model="parameters.id"
|
||||
@input="onSelect"
|
||||
|
||||
></selectable-component>
|
||||
</validation-wrapper-component>
|
||||
<list-component
|
||||
v-if="parameters.id"
|
||||
class="mt-4"
|
||||
:key="parameters.id"
|
||||
:section="`segments_${parameters.id}`"
|
||||
:endpoint="route('api.company.list')"
|
||||
:options="{
|
||||
company_segments_in: [parameters.id],
|
||||
// with_total_payments: true,
|
||||
// recency: '2022-02-15',
|
||||
// frequency: 15,
|
||||
// business_type: 2,
|
||||
// with_bookings: true,
|
||||
// order_by: { column: 'total_payments', DESC: true },
|
||||
}"
|
||||
>
|
||||
<template slot="list" slot-scope="{ data }">
|
||||
<company-component :data="data"></company-component>
|
||||
</template>
|
||||
</list-component>
|
||||
<div v-else>
|
||||
<div
|
||||
class="row align-items-center justify-content-center p-t-50 p-b-50"
|
||||
style=""
|
||||
>
|
||||
<div class="col-10">
|
||||
<div
|
||||
class="row align-items-center justify-content-center hint-text"
|
||||
>
|
||||
<div class="col-4 hint-text">
|
||||
<img
|
||||
src="/images/2829248.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"
|
||||
>
|
||||
Please Select a Segment
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import componentHandler from "../../../general/mixins/componentHandler";
|
||||
export default {
|
||||
props: {
|
||||
section: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
type: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
id: {
|
||||
type: Number,
|
||||
default: null,
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
parameters: {
|
||||
id: null,
|
||||
},
|
||||
};
|
||||
},
|
||||
validations: {
|
||||
parameters: {
|
||||
id: {},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onSelect(val) {
|
||||
this.parameters.id = val
|
||||
},
|
||||
},
|
||||
created(){
|
||||
const id = new URL(location.href).searchParams.get('id')
|
||||
if(id){
|
||||
this.parameters.id = id
|
||||
}
|
||||
},
|
||||
mixins: [componentHandler],
|
||||
};
|
||||
</script>
|
||||
@@ -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>
|
||||
|
||||
@@ -34,6 +34,15 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<a class="btn btn-xs btn-outline-info b-rad-none m-r-5 requestModal" :href="route('segments') + `?id=${item.id}`">
|
||||
<i class="fa fa-list"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto hide">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
|
||||
+6
-3
@@ -10,15 +10,18 @@ export default {
|
||||
},
|
||||
street_one: { required },
|
||||
street_two: {
|
||||
required: requiredIf(function(){
|
||||
return [7,8].includes(this.$store.getters.getCompanyModuleType);
|
||||
})
|
||||
required
|
||||
// required: requiredIf(function(){
|
||||
// return [7,8].includes(this.$store.getters.getCompanyModuleType);
|
||||
// })
|
||||
},
|
||||
district_id: { required },
|
||||
post_code: { required },
|
||||
remark: {},
|
||||
phone: {required, numeric},
|
||||
person_in_charge: { required },
|
||||
property_type: { required },
|
||||
additional_request: { },
|
||||
}
|
||||
},
|
||||
mixins: [addressFormHandler]
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user