mirror of
https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal.git
synced 2026-08-23 14:34:04 +00:00
Compare commits
92 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 735d14eef6 | |||
| 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 | |||
| d7aa248972 | |||
| 8e4ff6093e | |||
| 584169e173 | |||
| 14278a888a | |||
| 033a835fce | |||
| 66ddb5da23 | |||
| 65782ebf8a | |||
| 96a089df16 | |||
| f95545a985 | |||
| 9e8685bd02 | |||
| 1224735ba8 | |||
| 11e2390059 | |||
| c280da36d7 | |||
| 27529e90ca | |||
| 2e9b0f918c | |||
| 5565d0b39b | |||
| 73b3995367 | |||
| 252636a7df |
@@ -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"
|
||||
|
||||
@@ -65,7 +65,7 @@ abstract class AbstractControllerLogic
|
||||
|
||||
} catch (ErrorException|GeneralExceptions|TypeError $exception){
|
||||
if ($exception instanceof JobResourceNotFoundException) {
|
||||
Log::error(sprintf(
|
||||
Log::channel('vue_polling')->info(sprintf(
|
||||
"Uncaught exception '%s' with message '%s' in %s:%d",
|
||||
get_class($exception),
|
||||
$exception->getMessage(),
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -47,7 +47,7 @@ class UpdatePerfexCRMInvoice implements ShouldQueue
|
||||
$invoiceId = 0;
|
||||
$invoiceStatus = 0;
|
||||
$invoice = (App()->make(FetchesPerfexCRMInvoice::class))->execute($customer->userid,"INV-", $transaction->owner->bill_no);
|
||||
Log::error('UpdatePerfexCRMInvoice debug bill_no: ' . $transaction->owner->bill_no . ', Project Id: ' . $this->updatePerfexCRMInvoiceObject->getProjectId());
|
||||
Log::channel('perfex_crm')->info('UpdatePerfexCRMInvoice debug bill_no: ' . $transaction->owner->bill_no . ', Project Id: ' . $this->updatePerfexCRMInvoiceObject->getProjectId());
|
||||
|
||||
if(is_null($invoice)){
|
||||
$result = (App()->make(CreatePerfexCRMInvoiceProcessor::class))->execute($transaction->owner, $this->updatePerfexCRMInvoiceObject->getIsPaid());
|
||||
@@ -55,7 +55,7 @@ class UpdatePerfexCRMInvoice implements ShouldQueue
|
||||
$invoiceId = $result->payload['id'];
|
||||
} else {
|
||||
// Log::error(json_encode('UpdatePerfexCRMInvoice CreatePerfexCRMInvoiceProcessor failed'));
|
||||
Helper::debugLogger('UpdatePerfexCRMInvoice CreatePerfexCRMInvoiceProcessor failed');
|
||||
Log::channel('perfex_crm')->info('UpdatePerfexCRMInvoice CreatePerfexCRMInvoiceProcessor failed');
|
||||
}
|
||||
}
|
||||
else{
|
||||
|
||||
+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;
|
||||
|
||||
@@ -41,6 +41,9 @@ class ExportsPaymentTransactions implements FromQuery, WithHeadings, WithHeading
|
||||
'DeptNo',
|
||||
'Qty',
|
||||
'UnitPrice',
|
||||
'TaxType',
|
||||
'TaxableAmt',
|
||||
'TaxRate',
|
||||
// 'marking',
|
||||
// 'contact person',
|
||||
// 'contact number',
|
||||
@@ -130,6 +133,37 @@ 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'),
|
||||
$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'),
|
||||
|
||||
+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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ class FetchPerfexCRMInvoiceProcessor
|
||||
$invoiceId = $result->payload['id'];
|
||||
} else {
|
||||
$log['message'] = 'FetchPerfexCRMInvoiceProcessor failed for transaction > bill_no: '.$number;
|
||||
Helper::debugLogger($log);
|
||||
Log::channel('perfex_crm')->info($log);
|
||||
}
|
||||
}
|
||||
else{
|
||||
|
||||
@@ -25,7 +25,7 @@ class ConvertsPerfexCRMLeadToCustomer
|
||||
|
||||
return (object) $data;
|
||||
}else{
|
||||
Log::error('ConvertsPerfexCRMLeadToCustomer: '.$response);
|
||||
Log::channel('perfex_crm')->info('ConvertsPerfexCRMLeadToCustomer: '.$response);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ class CreatesPerfexCRMCustomer
|
||||
$data = $response->json();
|
||||
return (object) $data;
|
||||
}else{
|
||||
Log::error('CreatesPerfexCRMCustomer: '.$response);
|
||||
Log::channel('perfex_crm')->info('CreatesPerfexCRMCustomer: '.$response);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ class CreatesPerfexCRMCustomerContact
|
||||
$data = $response->json();
|
||||
return (object) $data;
|
||||
}else{
|
||||
Log::error('CreatesPerfexCRMCustomerContact: '.$response);
|
||||
Log::channel('perfex_crm')->info('CreatesPerfexCRMCustomerContact: '.$response);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ class CreatesPerfexCRMCustomerProject
|
||||
$data = $response->json();
|
||||
return (object) $data;
|
||||
}else{
|
||||
Log::error('CreatesPerfexCRMCustomerProject: '.$response);
|
||||
Log::channel('perfex_crm')->info('CreatesPerfexCRMCustomerProject: '.$response);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ class CreatesPerfexCRMInvoice
|
||||
$data = $response->json();
|
||||
return (object) $data;
|
||||
}else{
|
||||
Log::error('CreatesPerfexCRMInvoice: '.$response);
|
||||
Log::channel('perfex_crm')->info('CreatesPerfexCRMInvoice: '.$response);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ class CreatesPerfexCRMInvoicePayment
|
||||
$data = $response->json();
|
||||
return (object) $data;
|
||||
}else{
|
||||
Log::error('CreatesPerfexCRMInvoicePayment: '.$response);
|
||||
Log::channel('perfex_crm')->info('CreatesPerfexCRMInvoicePayment: '.$response);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ class CreatesPerfexCRMLead
|
||||
$data = $response->json();
|
||||
return (object) $data;
|
||||
}else{
|
||||
Log::error('CreatesPerfexCRMLead: '.$response);
|
||||
Log::channel('perfex_crm')->info('CreatesPerfexCRMLead: '.$response);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ class CreatesPerfexCRMMilestone
|
||||
$data = $response->json();
|
||||
return (object) $data;
|
||||
}else{
|
||||
Log::error('CreatesPerfexCRMMilestone: '.$response);
|
||||
Log::channel('perfex_crm')->info('CreatesPerfexCRMMilestone: '.$response);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ class CreatesPerfexCRMSupportTicket
|
||||
$data = $response->json();
|
||||
return (object) $data;
|
||||
}else{
|
||||
Log::error($response);
|
||||
Log::channel('perfex_crm')->info($response);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ class CreatesPerfexCRMTask
|
||||
$data = $response->json();
|
||||
return (object) $data;
|
||||
}else{
|
||||
Log::error('CreatesPerfexCRMTask: '.$response);
|
||||
Log::channel('perfex_crm')->info('CreatesPerfexCRMTask: '.$response);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ class FetchesPerfexCRMCustomer
|
||||
|
||||
return (object) $data;
|
||||
}else{
|
||||
Log::error('FetchesPerfexCRMCustomer: '.$response);
|
||||
Log::channel('perfex_crm')->info('FetchesPerfexCRMCustomer: '.$response);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ class FetchesPerfexCRMInvoice
|
||||
|
||||
return (object) $data;
|
||||
}else{
|
||||
Log::error('FetchesPerfexCRMInvoice: '.$response);
|
||||
Log::channel('perfex_crm')->info('FetchesPerfexCRMInvoice: '.$response);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ class FetchesPerfexCRMLead
|
||||
|
||||
return (object) $data;
|
||||
}else{
|
||||
Log::error('FetchesPerfexCRMLead: '.$response);
|
||||
Log::channel('perfex_crm')->info('FetchesPerfexCRMLead: '.$response);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ class FetchesPerfexCRMMilestone
|
||||
|
||||
return (object) $data;
|
||||
}else{
|
||||
Log::error('FetchesPerfexCRMMilestone: '.$response);
|
||||
Log::channel('perfex_crm')->info('FetchesPerfexCRMMilestone: '.$response);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ class FetchesPerfexCRMProject
|
||||
|
||||
return (object) $data;
|
||||
}else{
|
||||
Log::error('FetchesPerfexCRMProject: '.$response);
|
||||
Log::channel('perfex_crm')->info('FetchesPerfexCRMProject: '.$response);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ class FetchesPerfexCRMTask
|
||||
|
||||
return (object) $data;
|
||||
}else{
|
||||
Helper::debugLogger($response);
|
||||
Log::channel('perfex_crm')->info($response);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ class UpdatesPerfexCRMCustomer
|
||||
$data = $response->json();
|
||||
return (object) $data;
|
||||
}else{
|
||||
// Helper::debugLogger($response);
|
||||
// Log::channel('perfex_crm')->info($response);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ class UpdatesPerfexCRMInvoice
|
||||
$data = $response->json();
|
||||
return (object) $data;
|
||||
}else{
|
||||
Log::error('UpdatesPerfexCRMInvoice: '.$response);
|
||||
Log::channel('perfex_crm')->info('UpdatesPerfexCRMInvoice: '.$response);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ class UpdatesPerfexCRMLead
|
||||
$data = $response->json();
|
||||
return (object) $data;
|
||||
}else{
|
||||
Log::error('UpdatesPerfexCRMLead: '.$response);
|
||||
Log::channel('perfex_crm')->info('UpdatesPerfexCRMLead: '.$response);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ class UpdatesPerfexCRMProject
|
||||
$data = $response->json();
|
||||
return (object) $data;
|
||||
}else{
|
||||
Log::error('UpdatesPerfexCRMProject: '.$response);
|
||||
Log::channel('perfex_crm')->info('UpdatesPerfexCRMProject: '.$response);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ class UpdatesPerfexCRMTask
|
||||
$data = $response->json();
|
||||
return (object) $data;
|
||||
}else{
|
||||
Log::error('UpdatesPerfexCRMTask: '.$response);
|
||||
Log::channel('perfex_crm')->info('UpdatesPerfexCRMTask: '.$response);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,16 +82,35 @@ class CreateGroupsLogic extends AbstractControllerLogic
|
||||
|
||||
public function logic(Request $request) : JsonResponse
|
||||
{
|
||||
$payment_method = PaymentMethodType::PAYMENT_METHODS[$request->input('payment_method')];
|
||||
$groupPyamentStatus = ApprovalStatus::PENDING_VERIFICATION;
|
||||
|
||||
$invoice_ids = json_decode($request->route('transaction_ids'));
|
||||
$billNumber = $this->generatesTransactionBillNumber->execute('PYMT-');
|
||||
|
||||
// todo-new: check why is this not working
|
||||
// $invoices = $this->fetchesTransaction->execute(['id_in' => $invoice_ids]);
|
||||
$invoices = Transaction::whereIn('id', $invoice_ids)->get();
|
||||
$isInvoicesApprove = $this->checkIfInvoicesAreApprove($invoices);
|
||||
if(!$isInvoicesApprove){
|
||||
$response = ['message' => 'One of the transactions might be suspended; please check if there are any disputes in progress.'];
|
||||
return $this->response(['data' => $response]);
|
||||
}
|
||||
else{
|
||||
$paymentMethodStr = $request->input('payment_method');
|
||||
$paymentMethod = PaymentMethodType::PAYMENT_METHODS[$paymentMethodStr];
|
||||
$amount = $request->input('amount');
|
||||
$bankCode = $request->input('bank_code');
|
||||
$result = $this->processInvoices($invoices, $paymentMethodStr, $amount, $bankCode);
|
||||
|
||||
if ($paymentMethod === PaymentMethodType::PAYMENT_GATEWAY) {
|
||||
return $this->resourceResponse(new WalletTransactionResource($result));
|
||||
}
|
||||
}
|
||||
return $this->response([]);
|
||||
}
|
||||
|
||||
private function processInvoices($invoices, $reqPaymentMethod, $reqAmount, $reqBankCode){
|
||||
$result = [];
|
||||
$payment_method = PaymentMethodType::PAYMENT_METHODS[$reqPaymentMethod];
|
||||
$groupPyamentStatus = ApprovalStatus::PENDING_VERIFICATION;
|
||||
$billNumber = $this->generatesTransactionBillNumber->execute('PYMT-');
|
||||
foreach ($invoices as $invoice) {
|
||||
$order = null;
|
||||
if ($invoice->owner instanceof Transaction) {
|
||||
@@ -118,7 +137,7 @@ class CreateGroupsLogic extends AbstractControllerLogic
|
||||
$wallet = Wallet::where('owner_id', $companyModuleId)->first();
|
||||
|
||||
// todo-new: verify currently checking wallet amount based on 'amount' value passed by frontend
|
||||
if((float) number_format(($wallet->amount - $request->input('amount')),2) < 0){
|
||||
if((float) number_format(($wallet->amount - $reqAmount),2) < 0){
|
||||
throw new MalformedRequestException('Insufficient wallet balance. Please Top up your wallet.');
|
||||
}
|
||||
|
||||
@@ -154,7 +173,7 @@ class CreateGroupsLogic extends AbstractControllerLogic
|
||||
|
||||
foreach ($invoices as $invoice) {
|
||||
if ($payment_method == PaymentMethodType::WALLET) {
|
||||
$paymentTransaction = $this->createPaymentTransactionProcessor->execute($invoice, PaymentMethodType::WALLET, $request->input('bank_code'), false);
|
||||
$paymentTransaction = $this->createPaymentTransactionProcessor->execute($invoice, PaymentMethodType::WALLET, $reqBankCode, false);
|
||||
|
||||
if($paymentTransaction && $paymentTransaction->status == ApprovalStatus::APPROVED){
|
||||
$pL = $invoice->owner;
|
||||
@@ -181,11 +200,12 @@ class CreateGroupsLogic extends AbstractControllerLogic
|
||||
|
||||
if (in_array($payment_method, [PaymentMethodType::PAYMENT_GATEWAY, PaymentMethodType::CASH])) {
|
||||
// create only one billplz payment for wallet top up
|
||||
$amount = floatval(str_replace(',', '', $request->input('amount')));
|
||||
$amount = floatval(str_replace(',', '', $reqAmount));
|
||||
$companyModuleId = $invoice->receiver;
|
||||
$companyModule = $this->fetchesCompanyModule->execute(['id' => $companyModuleId]);
|
||||
|
||||
$topUpTransaction = $this->createWalletTopUpTransactionProcessor->execute($companyModule, $amount, $request->input('bank_code'), $payment_method, $billNumber, true);
|
||||
$topUpTransaction = $this->createWalletTopUpTransactionProcessor->execute($companyModule, $amount, $reqBankCode, $payment_method, $billNumber, true);
|
||||
$result = $topUpTransaction;
|
||||
}
|
||||
|
||||
$group->issuer = $issuer;
|
||||
@@ -201,11 +221,15 @@ class CreateGroupsLogic extends AbstractControllerLogic
|
||||
$group->status = $groupPyamentStatus;
|
||||
$group->save();
|
||||
|
||||
if ($payment_method === PaymentMethodType::PAYMENT_GATEWAY) {
|
||||
return $this->resourceResponse(new WalletTransactionResource($topUpTransaction));
|
||||
return $result;
|
||||
}
|
||||
|
||||
} else {
|
||||
return $this->response([]);
|
||||
private function checkIfInvoicesAreApprove($invoices){
|
||||
foreach ($invoices as $invoice) {
|
||||
if($invoice->status !== ApprovalStatus::APPROVED && $invoice->status !== ApprovalStatus::COMPLETED){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
+9
-19
@@ -52,28 +52,18 @@ class CreatePaymentTransactionLogic extends AbstractControllerLogic
|
||||
|
||||
$invoice_transaction = $this->fetchesTransaction->execute(['id' => $request->input('transaction_id')]);
|
||||
|
||||
$payment_transaction = $this->createPaymentTransactionProcessor->execute($invoice_transaction, $payment_method , $request->input('bank_code'), false);
|
||||
if($invoice_transaction->status === ApprovalStatus::APPROVED){
|
||||
$payment_transaction = $this->createPaymentTransactionProcessor->execute($invoice_transaction, $payment_method , $request->input('bank_code'), false);
|
||||
|
||||
if($payment_transaction && $payment_transaction->status == ApprovalStatus::APPROVED){
|
||||
$pL = $invoice_transaction->owner;
|
||||
$this->releaseGoodsToCustomerProcessor->execute($pL, $invoice_transaction);
|
||||
if($payment_transaction && $payment_transaction->status === ApprovalStatus::APPROVED){
|
||||
$pL = $invoice_transaction->owner;
|
||||
$this->releaseGoodsToCustomerProcessor->execute($pL, $invoice_transaction);
|
||||
}
|
||||
return $this->resourceResponse(new TransactionResource($payment_transaction));
|
||||
}
|
||||
|
||||
//cief todo: at exchange there is a transition step - starts
|
||||
// if(PaymentMethodType::PAYMENT_METHODS[$request->input('payment_method')] == PaymentMethodType::PAYMENT_GATEWAY){
|
||||
// $this->updatesTransactionStatus->execute($transaction, ApprovalStatus::PENDING_VERIFICATION);
|
||||
// }
|
||||
|
||||
// if(config('perfexcrm.is_enabled') == 'true'){
|
||||
// $this->transactionToPerfexCRMV2Processor->execute($transaction, $status);
|
||||
// }
|
||||
|
||||
//To use
|
||||
//ApprovalStatus::PENDING_VERIFICATION;
|
||||
//use this to trigger $this->transactionToPerfexCRMV2Processor->execute > defineTasks > defineTasks_handlePendingVerificationStatus > definePaymentTasks
|
||||
//cief todo: at exchange there is a transition step - ends
|
||||
|
||||
return $this->resourceResponse(new TransactionResource($payment_transaction));
|
||||
$response = ['message' => 'A transaction might be suspended; please check if there is any dispute in progress.'];
|
||||
return $this->response(['data' => $response]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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([]);
|
||||
}
|
||||
}
|
||||
+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,
|
||||
|
||||
+45
-20
@@ -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)
|
||||
@@ -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);
|
||||
|
||||
+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]);
|
||||
|
||||
@@ -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';
|
||||
}
|
||||
|
||||
@@ -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,73 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
|
||||
use App\Classes\Modules\Billplzs\Processors\CallbackBillplzProcessor;
|
||||
use App\Classes\ValueObjects\Constants\ApprovalStatus;
|
||||
use App\Models\Transaction;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class OneTimeTransactionFixBillplzFailedCallback extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'one-time-transaction-fix-billplz-failed-callback';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'This is a one time fix billplz failed callback for transaction with id 15205';
|
||||
|
||||
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();
|
||||
|
||||
//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.');
|
||||
|
||||
if($transaction && $transaction->id == 15205){
|
||||
|
||||
$status = ApprovalStatus::APPROVED;
|
||||
$this->callbackBillplzProcessor->execute($transaction, $status);
|
||||
}
|
||||
|
||||
|
||||
$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);
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ use App\Models\PermitsReminder;
|
||||
use App\Models\User;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class SendPermitsReminderEmails extends Command
|
||||
{
|
||||
@@ -41,23 +42,23 @@ class SendPermitsReminderEmails extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$now = now();
|
||||
$startRange = $now->subDays(3)->startOfDay();
|
||||
$endRange = $now->copy()->addDays(6)->endOfDay();
|
||||
$currentDateTime = now();
|
||||
$startRange = $currentDateTime->subDays(3)->startOfDay();
|
||||
$endRange = $currentDateTime->copy()->addDays(6)->endOfDay();
|
||||
|
||||
$reminders = PermitsReminder::whereDate('reminder_date', '>=', $startRange)
|
||||
->whereDate('reminder_date', '<=', $endRange)
|
||||
->orWhere('reminder_date', '<', now())
|
||||
->pluck('model');
|
||||
|
||||
$this->info($this->getTimeStamp() . json_encode($reminders));
|
||||
if ($reminders->isEmpty()) {
|
||||
$this->info('No reminders expiring within the specified range.');
|
||||
return;
|
||||
}
|
||||
|
||||
$users = User::whereIn(
|
||||
'email',
|
||||
[
|
||||
'edmond.wuiming2021@gmail.com',
|
||||
'anithagurl96@gmail.com'
|
||||
]
|
||||
)->get();
|
||||
$this->info($this->getTimeStamp() . 'Reminders: ' . $reminders->toJson());
|
||||
|
||||
$users = User::whereIn('email', $this->getEmailList())->get();
|
||||
|
||||
foreach ($users as $user) {
|
||||
$this->info($this->getTimeStamp() . 'Reminder email sent to ' . $user->email);
|
||||
@@ -71,4 +72,12 @@ class SendPermitsReminderEmails extends Command
|
||||
{
|
||||
return '[' . Carbon::now()->format('Y-m-d H:i:s') . '] - ';
|
||||
}
|
||||
|
||||
protected function getEmailList(): array
|
||||
{
|
||||
return [
|
||||
'edmond.wuiming2021@gmail.com',
|
||||
'anithagurl96@gmail.com'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Http\Controllers\PermitsReminder;
|
||||
|
||||
use App\Models\PermitsReminder;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
@@ -15,14 +16,25 @@ class ListPermitsReminderController
|
||||
public function list(Request $request): JsonResponse
|
||||
{
|
||||
$perPage = 10; // Number of items per page
|
||||
$page = request('page', 1); // Get the current page from the request
|
||||
$page = $request->query('page', 1); // Get the current page from the request
|
||||
|
||||
// Paginate the PermitsReminder model
|
||||
$query = PermitsReminder::orderBy('id', 'desc');
|
||||
$paginator = $query->paginate($perPage, ['*'], 'page', $page);
|
||||
$paginator = PermitsReminder::orderBy('reminder_date')->paginate($perPage, ['*'], 'page', $page);
|
||||
|
||||
// Convert paginated data to an array
|
||||
// Get current date and time
|
||||
$currentDateTime = now();
|
||||
|
||||
// Define date range
|
||||
$startRange = $currentDateTime->subDays(3)->startOfDay();
|
||||
$endRange = $currentDateTime->copy()->addDays(6)->endOfDay();
|
||||
|
||||
// Process paginated items
|
||||
$data = $paginator->items();
|
||||
foreach ($data as &$item) {
|
||||
// Check if the reminder_date is within the date range or after the current date
|
||||
$reminderDate = Carbon::parse($item->reminder_date);
|
||||
$item->show_remind = $reminderDate->between($startRange, $endRange) || $reminderDate->isBefore($currentDateTime);
|
||||
}
|
||||
|
||||
// Create pagination links
|
||||
$links = [
|
||||
@@ -32,6 +44,7 @@ class ListPermitsReminderController
|
||||
"next" => $paginator->nextPageUrl(),
|
||||
];
|
||||
|
||||
// Prepare response
|
||||
$response = [
|
||||
"title" => "List Permits Reminder",
|
||||
"message" => "You have successfully retrieved a list of Permits Reminder",
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace App\Http\Controllers\Transactions;
|
||||
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Classes\Modules\Transactions\ControllersLogic\DeletePaidGroupLogic;
|
||||
|
||||
class DeletePaidGroupController
|
||||
{
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param DeleteGroupTransactionLogic $logic
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function delete(Request $request, DeletePaidGroupLogic $logic) : JsonResponse {
|
||||
return $logic->execute($request);
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,12 @@ class CheckForStorageInvoiceByOrderId
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
$orderId = $request->route('id');
|
||||
$storages = $this->storageInvoiceTransactionProcessor->execute($orderId);
|
||||
$storages = [];
|
||||
try{
|
||||
$storages = $this->storageInvoiceTransactionProcessor->execute($orderId);
|
||||
} catch (\Exception $exception) {
|
||||
$storages = [];
|
||||
}
|
||||
$request->merge(['storages' => $storages]);
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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
|
||||
];
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -54,6 +55,10 @@ 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) {
|
||||
@@ -119,6 +124,7 @@ class TransactionWithStorageResource extends JsonResource
|
||||
->get()
|
||||
),
|
||||
'remarks' => RemarkResource::collection($this->remarks),
|
||||
'packing_list_reference' => $packingListReference,
|
||||
'storages' => $this->storages ? $this->storages : null, //from middleware
|
||||
'is_waived' => (int) $this->is_waived,
|
||||
'expires_on' => Carbon::parse($this->expires_on)->format('d-m-Y h:i:s A'),
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -112,6 +112,24 @@ return [
|
||||
'path' => storage_path('logs/paymentUnknownOrderLog.log'),
|
||||
'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'),
|
||||
'level' => 'info',
|
||||
],
|
||||
|
||||
'perfex_crm' => [
|
||||
'driver' => 'single',
|
||||
'path' => storage_path('logs/laravel_perfex_crm.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');
|
||||
});
|
||||
}
|
||||
}
|
||||
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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
+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) {
|
||||
|
||||
@@ -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,11 @@
|
||||
<script>
|
||||
import componentHandler from '../../../general/mixins/componentHandler';
|
||||
export default {
|
||||
mixins: [componentHandler]
|
||||
mixins: [componentHandler],
|
||||
data() {
|
||||
return {
|
||||
isLoading: false
|
||||
}
|
||||
}
|
||||
}
|
||||
</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>
|
||||
@@ -215,6 +216,11 @@
|
||||
this.isLoading = false;
|
||||
this.order = response.payload.data;
|
||||
},
|
||||
errorHandler(error, status){
|
||||
if(status == 404){
|
||||
window.location.href = this.route('error.404');
|
||||
}
|
||||
},
|
||||
getStorageInfo(invoice) {
|
||||
const storageObject = this.findStorageInfoObject(invoice.id);
|
||||
return storageObject;
|
||||
|
||||
-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(){
|
||||
|
||||
+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>
|
||||
|
||||
+1
-1
@@ -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">
|
||||
|
||||
-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>
|
||||
+1
-1
@@ -81,7 +81,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">
|
||||
|
||||
+15
-6
@@ -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">
|
||||
@@ -138,7 +138,7 @@
|
||||
<div class="btn btn-sm all-caps b-rad-none btn-default bg-master-lighter btn-block" @click="expandPayment = false" data-dismiss="modal">Cancel</div>
|
||||
</div>
|
||||
<div class="col-8 p-l-0">
|
||||
<div class="btn btn-sm all-caps b-rad-none btn-default bg-success btn-block text-white" @click="submitForm()" :class="[{'hide': paymentMethod.name === ''}]" data-dismiss="modal">Proceed</div>
|
||||
<div class="btn btn-sm all-caps b-rad-none btn-default bg-success btn-block text-white" @click="submitForm()" :class="[{'hide': paymentMethod.name === ''}]">Proceed</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -202,8 +202,9 @@
|
||||
},
|
||||
methods:{
|
||||
submitForm(){
|
||||
this.error = '';
|
||||
this.parameters.payment_method = this.paymentMethod.id;
|
||||
this.submit(this.route('api.transaction.group.create', JSON.stringify(this.selectedIds)), 'post', this.section, true, true);
|
||||
this.submit(this.route('api.transaction.group.create', JSON.stringify(this.selectedIds)), 'post', this.section, false, true);
|
||||
},
|
||||
updatePaymentType(payment){
|
||||
this.paymentMethod = {
|
||||
@@ -224,11 +225,17 @@
|
||||
// }
|
||||
// }
|
||||
|
||||
if (response.payload.length == 0) {
|
||||
let isClearToUpdateList = true;
|
||||
if(response.payload.data && response.payload.data.message){
|
||||
this.error = response.payload.data.message;
|
||||
isClearToUpdateList = false;
|
||||
}
|
||||
else if (response.payload.length == 0) {
|
||||
setTimeout(function() {
|
||||
location.reload();
|
||||
}, 2000);
|
||||
} else if (response.payload) {
|
||||
}
|
||||
else if (response.payload) {
|
||||
if (response.payload.data.payment_method === 5) {
|
||||
window.location.href = this.route('billplz.bill', response.payload.data.reference) + '?auto_submit=true';
|
||||
} else {
|
||||
@@ -236,7 +243,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
this.updateList();
|
||||
if(isClearToUpdateList){
|
||||
this.updateList();
|
||||
}
|
||||
}
|
||||
},
|
||||
mixins: [formHandler]
|
||||
|
||||
@@ -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">
|
||||
@@ -97,7 +97,7 @@
|
||||
<div class="btn btn-sm all-caps b-rad-none btn-default bg-master-lighter btn-block" @click="expandPayment = false" data-dismiss="modal">Cancel</div>
|
||||
</div>
|
||||
<div class="col-8 p-l-0">
|
||||
<div class="btn btn-sm all-caps b-rad-none btn-default bg-success btn-block text-white" @click="submitForm()" :class="[{'hide': paymentMethod.name === ''}]" data-dismiss="modal">Proceed</div>
|
||||
<div class="btn btn-sm all-caps b-rad-none btn-default bg-success btn-block text-white" @click="submitForm()" :class="[{'hide': paymentMethod.name === ''}]">Proceed</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -134,8 +134,9 @@
|
||||
},
|
||||
methods:{
|
||||
submitForm(){
|
||||
this.error = '';
|
||||
this.parameters.payment_method = this.paymentMethod.id;
|
||||
this.submit(this.route('api.transaction.payment.create'), 'post', 'orderProfileSection', true, true);
|
||||
this.submit(this.route('api.transaction.payment.create'), 'post', 'orderProfileSection', false, true);
|
||||
},
|
||||
updatePaymentType(payment){
|
||||
this.paymentMethod = {
|
||||
@@ -152,7 +153,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
this.updateList();
|
||||
if(response.payload.data && response.payload.data.message){
|
||||
this.error = response.payload.data.message;
|
||||
}
|
||||
else{
|
||||
this.closeModal();
|
||||
this.updateList();
|
||||
}
|
||||
}
|
||||
},
|
||||
mixins: [formHandler]
|
||||
|
||||
+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">
|
||||
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
|
||||
const state = {
|
||||
pollingJobResults: []
|
||||
};
|
||||
|
||||
export default {
|
||||
state,
|
||||
getters: {
|
||||
getJob: (state) => (name) => {
|
||||
return state.pollingJobResults.find(item => item.name === name);;
|
||||
},
|
||||
getJobAttemptCount: (state) => (name) => {
|
||||
let job = state.pollingJobResults.find(item => item.name === name);
|
||||
return job ? job.pollingAttemptsCount : 0;
|
||||
},
|
||||
},
|
||||
mutations: {
|
||||
ADD_POLLING_JOB_RESULT(state, {jobId, name, pollingAttemptsCount, isPolling, isFetchingResult, maxAttempts, pollJobResult, interval}) {
|
||||
let intervalId = setInterval(() => {
|
||||
if (pollJobResult) {
|
||||
pollJobResult(state);
|
||||
}
|
||||
}, interval);
|
||||
state.pollingJobResults.push({ jobId, name, pollingAttemptsCount, isPolling, isFetchingResult, maxAttempts, intervalId});
|
||||
},
|
||||
UPDATE_POLLING_JOB_RESULT(state, { jobId, pollingAttemptsCount, isPolling, isFetchingResult, isLastAttempt}) {
|
||||
const index = state.pollingJobResults.findIndex(s => s.jobId === jobId);
|
||||
if (index !== -1) {
|
||||
const updatedPollingJobResults = [...state.pollingJobResults];
|
||||
updatedPollingJobResults[index] = { ...updatedPollingJobResults[index],
|
||||
jobId,
|
||||
pollingAttemptsCount: pollingAttemptsCount !== undefined ? pollingAttemptsCount : updatedPollingJobResults[index].pollingAttemptsCount,
|
||||
isPolling: isPolling !== undefined ? isPolling : updatedPollingJobResults[index].isPolling,
|
||||
isFetchingResult: isFetchingResult !== undefined ? isFetchingResult : updatedPollingJobResults[index].isFetchingResult,
|
||||
isLastAttempt: isLastAttempt !== undefined ? isLastAttempt : updatedPollingJobResults[index].isLastAttempt,
|
||||
};
|
||||
state.pollingJobResults = updatedPollingJobResults;
|
||||
}
|
||||
},
|
||||
REMOVE_POLLING_JOB_RESULT_BY_JOBID(state, jobId) {
|
||||
const index = state.pollingJobResults.findIndex(s => s.jobId === jobId);
|
||||
if (index !== -1) {
|
||||
clearInterval(state.pollingJobResults[index].intervalId);
|
||||
state.pollingJobResults.splice(index, 1);
|
||||
}
|
||||
},
|
||||
// REMOVE_POLLING_JOB_RESULT_BY_JOBID_2(state, jobId) {
|
||||
// const index = state.pollingJobResults.findIndex(s => s.jobId === jobId);
|
||||
// if (index !== -1) {
|
||||
// clearInterval(state.pollingJobResults[index].intervalId);
|
||||
// //state.pollingJobResults.splice(index, 1);
|
||||
// }
|
||||
// },
|
||||
REMOVE_POLLING_JOB_RESULT_BY_NAME(state, name) {
|
||||
const index = state.pollingJobResults.findIndex(s => s.name === name);
|
||||
if (index !== -1) {
|
||||
clearInterval(state.pollingJobResults[index].intervalId);
|
||||
state.pollingJobResults.splice(index, 1);
|
||||
}
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
submitJobRequest({ dispatch }, { url, name }){
|
||||
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){
|
||||
let pollingAttemptsCount = 0;
|
||||
dispatch('startPolling', { jobId, name, pollingAttemptsCount });
|
||||
}
|
||||
});
|
||||
})
|
||||
},
|
||||
|
||||
stopPollingJobResultByJobId({ commit }, { jobId }){
|
||||
commit('REMOVE_POLLING_JOB_RESULT_BY_JOBID', jobId);
|
||||
},
|
||||
|
||||
stopPollingJobResultByName({ commit }, { name }){
|
||||
commit('REMOVE_POLLING_JOB_RESULT_BY_NAME', name);
|
||||
},
|
||||
|
||||
startPolling({ state, commit, dispatch }, { jobId, name, pollingAttemptsCount, maxAttempts = 8}) {
|
||||
let interval = 10000;
|
||||
|
||||
// console.log(`startPolling jobId: ${jobId}, pollingAttemptsCount: ${pollingAttemptsCount}, name: ${name}`);
|
||||
|
||||
const pollJobResult = (state) => {
|
||||
//console.log(`MONITOR state ${JSON.stringify(state)}`);
|
||||
const index = state.pollingJobResults.findIndex(s => s.jobId === jobId);
|
||||
if (index !== -1) {
|
||||
pollingAttemptsCount = state.pollingJobResults[index].pollingAttemptsCount;
|
||||
if (state.pollingJobResults[index].isPolling || state.pollingJobResults[index].isFetchingResult) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else{
|
||||
return;
|
||||
}
|
||||
|
||||
pollingAttemptsCount++;
|
||||
if(pollingAttemptsCount === 1){
|
||||
commit("REMOVE_POLLING_JOB_RESULT_BY_JOBID", jobId );
|
||||
commit("ADD_POLLING_JOB_RESULT", { jobId, name, pollingAttemptsCount, isPolling: false, isFetchingResult: false, maxAttempts, pollJobResult, interval: 5000});
|
||||
}
|
||||
|
||||
if (pollingAttemptsCount > maxAttempts) {
|
||||
//console.log(`Reached maximum attempts (${maxAttempts}). Polling stopped.`);
|
||||
commit("REMOVE_POLLING_JOB_RESULT_BY_JOBID", jobId );
|
||||
return;
|
||||
}
|
||||
|
||||
if(pollingAttemptsCount === maxAttempts){
|
||||
commit('UPDATE_POLLING_JOB_RESULT', { jobId, pollingAttemptsCount, isPolling: true, isFetchingResult: false, isLastAttempt: true });
|
||||
}
|
||||
else{
|
||||
commit('UPDATE_POLLING_JOB_RESULT', { jobId, pollingAttemptsCount, isPolling: true, isFetchingResult: false, isLastAttempt: false});
|
||||
}
|
||||
}
|
||||
commit("ADD_POLLING_JOB_RESULT", { jobId, name, pollingAttemptsCount, isPolling: false, isFetchingResult: false, maxAttempts, pollJobResult, interval});
|
||||
|
||||
},
|
||||
|
||||
updatePollingJobResultByJobId({ commit }, { jobId, isPolling, isFetchingResult }){
|
||||
commit('UPDATE_POLLING_JOB_RESULT', { jobId, isPolling, isFetchingResult });
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+3
-1
@@ -7,6 +7,7 @@ import crudRequest from './modules/crudRequest'
|
||||
import crudRequestV2 from './modules/crudRequestV2'
|
||||
import authentication from './modules/authentication'
|
||||
import loadRequestQueue from './modules/loadRequestQueue'
|
||||
import jobPolling from './modules/jobPolling'
|
||||
|
||||
Vue.use(Vuex);
|
||||
|
||||
@@ -18,6 +19,7 @@ export default new Vuex.Store({
|
||||
createNotification,
|
||||
crudRequest,
|
||||
crudRequestV2,
|
||||
authentication
|
||||
authentication,
|
||||
jobPolling
|
||||
}
|
||||
})
|
||||
|
||||
@@ -4,10 +4,16 @@
|
||||
@include('vendor/head')
|
||||
</head>
|
||||
<body class="horizontal-menu horizontal-app-menu bg-white overflow-hidden">
|
||||
<!-- Google Tag Manager (noscript) -->
|
||||
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-T3XCNMB"
|
||||
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
|
||||
<!-- End Google Tag Manager (noscript) -->
|
||||
<!-- Google tag (gtag.js) -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-SP04J05142"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'G-SP04J05142');
|
||||
</script>
|
||||
<!-- End Google Tag Manager -->
|
||||
<div id="app" style="min-height: 100%;">
|
||||
@yield('content')
|
||||
</div>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user