Compare commits

...

78 Commits

Author SHA1 Message Date
Aqqil Azman 679d53ab57 initial commit for ToolsRequiredComponent and its options 2024-06-19 11:55:11 +08:00
Aqqil Azman d9377c0196 use tools-required-component instead of select-component 2024-06-19 11:54:55 +08:00
Aqqil Azman e6fa771ecc added Vue-multi-select dependency 2024-06-19 11:53:59 +08:00
Aqqil Azman b2a22d2739 Merge branch 'change-delivery-address-form-update' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into vue-multi-select-implementation 2024-06-18 14:17:37 +08:00
Dillon Ngo fd75da5778 Merge branch 'dillon/51.5-vue-store-update' into 'master'
A minor fix to not allow non-admin user to see admin data by navigating to the...

See merge request CIEFWorldwideSdnBhd/shipping-portal!229
2024-06-17 00:58:05 +00:00
Dillon Ngo b593605c72 A minor fix to not allow non-admin user to see admin data by navigating to the url /payment-and-billing-2 2024-06-17 08:51:09 +08:00
Dillon Ngo 8d75012390 Merge branch 'dillon/62.1-fixes' into 'master'
Reinstate original code after data patch

See merge request CIEFWorldwideSdnBhd/shipping-portal!228
2024-06-16 06:14:47 +00:00
Dillon Ngo 2d98757c1c Data patch meant to fix a group payment with group id 609 and transaction id 16803 that got stuck after making paying 2024-06-16 14:13:09 +08:00
Dillon Ngo b329f232f2 Merge branch 'dillon/62.1-fixes' into 'master'
Data patch meant to fix a group payment with group id 609 and transaction id...

See merge request CIEFWorldwideSdnBhd/shipping-portal!227
2024-06-16 06:06:54 +00:00
Dillon Ngo 713922d2ee Data patch meant to fix a group payment with group id 609 and transaction id 16803 that got stuck after making paying 2024-06-16 14:04:16 +08:00
Dillon Ngo 74d11f8305 Merge branch 'dillon/62.1-fixes' into 'master'
Fix a rounding problem in group payment which will result in goods cannot be...

See merge request CIEFWorldwideSdnBhd/shipping-portal!226
2024-06-14 21:58:25 +00:00
Dillon Ngo ea920717a1 Fix a rounding problem in group payment which will result in goods cannot be released through CallbackBillplzLogic 2024-06-15 05:56:23 +08:00
Dillon Ngo e1b49f6be0 Merge branch 'dillon/46.13-missing-payment-proof-feature' into 'master'
Restore missing payment proof feature

See merge request CIEFWorldwideSdnBhd/shipping-portal!224
2024-06-14 21:45:15 +00:00
edmondlang 1be405ca93 fix error message in admin dashbaord 2024-06-13 23:47:43 +08:00
Aqqil Azman 928430caec changed property type and tools required dropdown into vue Select-component 2024-06-12 01:39:45 +08:00
Aqqil Azman 5d01757d60 added pickup_time, latest_pickup_time, property_type and tools_required 2024-06-12 01:38:42 +08:00
Aqqil Azman 4f704ef6a0 updated address form component with Hours, Property Type and Tools Required 2024-06-11 10:20:09 +08:00
Dillon Ngo e63e3e707f 'Your Payment Proof' feature missing for order with storage invoices through group payment 2024-06-09 12:44:19 +08:00
Dillon Ngo aeaec32dcb 'Your Payment Proof' feature missing for order with storage invoices through group payment 2024-06-09 12:16:18 +08:00
Dillon Ngo b000c25e66 'Your Payment Proof' feature missing for order with storage invoices through group payment 2024-06-09 12:00:19 +08:00
edmondlang 1e9af59b91 test gtag 2024-06-07 17:40:48 +08:00
edmondlang a392b8a5eb test ga4 2024-06-07 17:35:57 +08:00
edmondlang 30edc3eaba updates RescheduleContainerLogic delete all the previous container transport schedule, then create a new one 2024-05-30 23:08:05 +08:00
edmondlang b0eca18343 show packinglist reference for admin only 2024-05-27 00:53:48 +08:00
Dillon Ngo 88e1b43f19 Merge branch 'dillon/46.11-warehouse-storage-related-fixes' into 'master'
Inserted logs for monitoring warehouse storage charges

See merge request CIEFWorldwideSdnBhd/shipping-portal!223
2024-05-26 08:58:20 +00:00
omair saleh fc9f6d6dde Merge branch 'fulfilment-banner' into 'master'
fix segment requried contact bug

See merge request CIEFWorldwideSdnBhd/shipping-portal!222
2024-05-24 06:52:53 +00:00
Jia Sheng 141dab15b6 fix segment requried contact bug 2024-05-23 11:44:18 +08:00
edmondlang c9ac435e37 update confirmation message 2024-05-21 01:33:24 +08:00
edmondlang 6d01bdfb60 Merge branch 'fulfilment-banner' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal 2024-05-21 01:27:47 +08:00
edmondlang e2dc83e441 add segments in the menu bar. 2024-05-21 01:26:09 +08:00
Jia Sheng e9daadaf60 not interested confirmation 2024-05-21 01:25:14 +08:00
edmondlang 7cace7e800 Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into fulfilment-banner 2024-05-21 00:54:21 +08:00
Jia Sheng 64fa56c02f fulfilment banner flow update, segment user index list 2024-05-20 22:51:22 +08:00
Dillon Ngo 3f962e774d Merge branch 'dillon/51.5-vue-store-update' into 'master'
Vue Polling - Fix minor typo error

See merge request CIEFWorldwideSdnBhd/shipping-portal!221
2024-05-19 19:14:56 +00:00
Dillon Ngo 4ba2144f02 Vue Polling - Fix minor typo error 2024-05-20 02:28:49 +08:00
Dillon Ngo 69f2b384cf Merge branch 'dillon/51.5-vue-store-update' into 'master'
Vue Polling - Refactor code to use vuex

See merge request CIEFWorldwideSdnBhd/shipping-portal!220
2024-05-19 16:06:00 +00:00
Dillon Ngo f1a35299e6 Vue Polling - Remove unnecessary code 2024-05-19 23:48:40 +08:00
Dillon Ngo b15866ea16 Vue Polling - Remove comments in code 2024-05-19 23:47:00 +08:00
Dillon Ngo bd42f7213a Vue Polling - Refactor code to use vuex 2024-05-18 18:55:21 +08:00
jiasheng224 2d92b1a8ab fulfilment banner module 2024-05-08 18:30:12 +08:00
Dillon Ngo 06e3049e50 Debugging 2024-05-08 03:03:58 +08:00
Dillon Ngo b0fa73a12b Debugging 2024-05-08 01:52:51 +08:00
Dillon Ngo 5d66761465 Merge branch 'dillon/60-shipping-portal-fixes' into 'master'
Deleted a file that should no longer be used

See merge request CIEFWorldwideSdnBhd/shipping-portal!219
2024-05-07 16:53:13 +00:00
Dillon Ngo 1ac4615c99 Delete a file that should no longer be used 2024-05-08 00:52:33 +08:00
Dillon Ngo 590960b5fd Merge branch 'dillon/60-shipping-portal-fixes' into 'master'
Move a file that should no longer be used (deprecated)

See merge request CIEFWorldwideSdnBhd/shipping-portal!218
2024-05-07 16:50:42 +00:00
Dillon Ngo 5f24f58480 Move a file that should no longer be used 2024-05-08 00:48:15 +08:00
edmondlang 4dec576aa0 Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal 2024-05-08 00:31:22 +08:00
edmondlang 4a41c89024 fix MappableTransactionWithDetailsResource.php 2024-05-08 00:30:01 +08:00
Dillon Ngo a0997a4649 Merge branch 'dillon/60-shipping-portal-fixes' into 'master'
Fix a problem with inefficient query discovered from Laravel Vapor integration (payment and billing page, pending payment tab)

See merge request CIEFWorldwideSdnBhd/shipping-portal!217
2024-05-07 16:27:55 +00:00
Dillon Ngo b90dae882e Fix a problem with inefficient query discovered from Laravel Vapor integration 2024-05-08 00:26:12 +08:00
edmondlang f361a7e185 fix MappableTransactionWithDetailsResource.php 2024-05-08 00:24:22 +08:00
Dillon Ngo 29619625d1 Merge branch 'dillon/46.11-warehouse-storage-related-fixes' into 'master'
Fix multipe interface user experience (UX) problem originally reported by Yien

See merge request CIEFWorldwideSdnBhd/shipping-portal!216
2024-05-07 16:15:11 +00:00
Dillon Ngo 1705b5c2e5 Fix a front end UX problem reported by Yien 2024-05-06 13:19:23 +08:00
Dillon Ngo 1813783d87 Merge branch 'dillon/60-shipping-portal-fixes' into 'master'
Fix emails cannot be sent with attachment

See merge request CIEFWorldwideSdnBhd/shipping-portal!215
2024-05-04 09:53:01 +00:00
Dillon Ngo 46a0e670ba Fix emails cannot be sent with attachment 2024-05-04 17:51:57 +08:00
Omair Saleh dcec8cb33b update payment export itemization 2024-04-18 02:27:35 +08:00
Omair Saleh 75037f6192 update payment export itemization 2024-04-18 02:22:30 +08:00
Omair Saleh 675324081b update payment export itemization 2024-04-18 02:21:30 +08:00
Omair Saleh a959e83f5b update payment export itemization 2024-04-18 02:19:05 +08:00
Omair Saleh 2802e3c366 update payment export itemization 2024-04-18 02:17:43 +08:00
Omair Saleh aac2a0666a update payment export itemization 2024-04-18 02:16:13 +08:00
Omair Saleh 19efba4b89 update payment export itemization 2024-04-18 02:13:43 +08:00
Omair Saleh 7d70c800db update payment export itemization 2024-04-18 02:12:55 +08:00
Omair Saleh 863dc94dad Revert "Revert "Merge branch 'dillon/58-shipping-portal-sst' into 'master'""
This reverts commit a49920973e.
2024-04-18 02:09:16 +08:00
Omair Saleh 98e45e27e3 update payment export itemization 2024-04-18 02:04:56 +08:00
Omair Saleh df2916594b remove invoice date adjuster 2024-04-18 01:14:39 +08:00
Omair Saleh a49920973e Revert "Merge branch 'dillon/58-shipping-portal-sst' into 'master'"
This reverts commit 7cd376a9b5, reversing
changes made to 6176135f85.
2024-04-16 13:21:07 +08:00
Omair Saleh d129f8f6bd clear wrong date invoice from april to march 2024-04-16 13:17:23 +08:00
Omair Saleh 55a82e52a4 Merge remote-tracking branch 'origin/master' 2024-04-16 13:02:53 +08:00
Omair Saleh 1d4ac80b8f change sst invoice format 2024-04-16 13:02:40 +08:00
omair saleh 7cd376a9b5 Merge branch 'dillon/58-shipping-portal-sst' into 'master'
Dillon/58 shipping portal sst

See merge request CIEFWorldwideSdnBhd/shipping-portal!213
2024-04-16 04:51:39 +00:00
Omair Saleh c7e3091f9b change sst invoice format 2024-04-16 12:49:46 +08:00
Omair Saleh 28feba2ae9 change sst invoice format 2024-04-16 12:39:44 +08:00
edmondlang 6176135f85 fix qr api issue 2024-04-10 23:17:05 +08:00
edmondlang 5f529965da Merge branch 'qr-api-issue' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal 2024-04-10 22:27:29 +08:00
jiasheng224 5f5bbe0c8c update wallet balance when credit or debit to wallet balance 2024-04-09 16:58:12 +08:00
Dillon Ngo a809aec9a7 SST Impelemtation 2024-04-07 10:22:12 +08:00
Dillon Ngo 68ce8373e9 SST Impelemtation 2024-04-07 09:27:09 +08:00
69 changed files with 1884 additions and 895 deletions
+4
View File
@@ -59,3 +59,7 @@ YD_API_CODE=''
PERFEXCRM_BASE_URL=""
PERFEXCRM_API_KEY=""
PERFEXCRM_IS_ENABLED="false"
STORAGE_FEE_LAUNCH_DATE="2023-12-11 00:00:00"
SST_START_DATE="2024-04-01 00:00:00"
@@ -0,0 +1,24 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class CompanySegmentsIn implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->whereHas('companyModules', function ($module) use ($value) {
$module->whereHas('connections', function ($connection) use ($value) {
$connection->whereHas('connectionSegments', function ($segment) use ($value) {
$segment->whereIn('segment_id', $value);
});
});
});
}
}
@@ -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));
}
}
@@ -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'),
@@ -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));
}
}
@@ -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);
}
}
@@ -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,
@@ -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;
}
}
}
@@ -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,
@@ -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);
@@ -0,0 +1,188 @@
<?php
namespace App\Classes\Modules\Transactions\Processors;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Modules\Transactions\Services\FetchesTransaction;
use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber;
use App\Classes\Modules\Transactions\Services\CreatesPaymentTransaction;
use App\Classes\Modules\Transactions\Services\CreatesTransactionDetail;
use App\Classes\Modules\Billplzs\Services\CreatesBillplzBill;
use App\Classes\Modules\Transactions\Services\CreatesTransactionableTransaction;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\Modules\Wallets\Services\UpdatesWalletBalance;
use App\Models\Transaction;
use App\Models\Wallet;
use App\Classes\Modules\Orders\Processors\UpdateDoFromVTPortalProcessor;
use App\Classes\Modules\Orders\Processors\UpdateDoFromYDPortalProcessor;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use Illuminate\Support\Facades\Log;
//DATE: 20240616
//THIS IS A ONE TIME FIX PROCESSOR MEANT TO FIX A GROUP PAYMENT THAT GOT STUCK: https://izyim.cief-malaysia.com/customer/943GCC/payment-and-billing
//TRNASACTION WITH ID: 16803
//GROUP WITH ID: 609
class CreatePaymentTransactionOneTimeFixProcessor
{
/** @var GeneratesTransactionBillNumber */
private $generatesTransactionBillNumber;
/** @var CreatesPaymentTransaction */
private $createsPaymentTransaction;
/** @var CreatesBillplzBill */
private $createsBillplzBill;
/** @var CreatesTransactionableTransaction */
private $createsTransactionableTransaction;
/** @var UpdatesWalletBalance */
private $updatesWalletBalance;
/** @var UpdateDoFromVTPortalProcessor */
private $updateDoFromVTPortalProcessor;
/** @var UpdateDoFromYDPortalProcessor */
private $updateDoFromYDPortalProcessor ;
/** @var UpdatesTransactionStatus */
private $updatesTransactionStatus ;
/**
* @param FetchesTransaction $fetchesTransaction,
* @param GeneratesTransactionBillNumber $generatesTransactionBillNumber,
* @param CreatesPaymentTransaction $createsPaymentTransaction
* @param CreatesTransactionDetail $createsTransactionDetail
* @param CreatesBillplzBill $createsBillplzBil
* @param CreatesTransactionableTransaction $createsTransactionableTransaction
* @param UpdatesWalletBalance $updatesWalletBalance
* @param UpdateDoFromVTPortalProcessor $updateDoFromVTPortalProcessor
* @param UpdateDoFromYDPortalProcessor $updateDoFromYDPortalProcessor
* @param UpdatesTransactionStatus $updatesTransactionStatus
*/
public function __construct(
GeneratesTransactionBillNumber $generatesTransactionBillNumber,
CreatesPaymentTransaction $createsPaymentTransaction,
CreatesBillplzBill $createsBillplzBill,
CreatesTransactionableTransaction $createsTransactionableTransaction,
UpdatesWalletBalance $updatesWalletBalance,
UpdateDoFromVTPortalProcessor $updateDoFromVTPortalProcessor,
UpdateDoFromYDPortalProcessor $updateDoFromYDPortalProcessor,
UpdatesTransactionStatus $updatesTransactionStatus
)
{
$this->generatesTransactionBillNumber = $generatesTransactionBillNumber;
$this->createsPaymentTransaction = $createsPaymentTransaction;
$this->createsBillplzBill = $createsBillplzBill;
$this->createsTransactionableTransaction = $createsTransactionableTransaction;
$this->updatesWalletBalance = $updatesWalletBalance;
$this->updateDoFromVTPortalProcessor = $updateDoFromVTPortalProcessor;
$this->updateDoFromYDPortalProcessor = $updateDoFromYDPortalProcessor;
$this->updatesTransactionStatus = $updatesTransactionStatus;
}
/**
* @throws MalformedRequestException
*/
public function execute(Transaction $invoice, $payment_method, $bank_code, $date, $run = true)
{
$amount = $invoice->amount;
Log::info($invoice->owner);
$company_module = $invoice->owner->owner->companyModule()->first();
$approvalStatus = ApprovalStatus::PENDING_SUBMISSION;
$billNumber = $this->generatesTransactionBillNumber->execute('PYMT-');
$payment_reference = null;
if ($payment_method == PaymentMethodType::PAYMENT_GATEWAY) {
// create billplz transaction
$payment_method = PaymentMethodType::PAYMENT_GATEWAY;
$billPlzBill = $this->createsBillplzBill->execute(
$company_module->name,
(app()->environment(['production'])) ? $company_module->employees()->first()->email : 'uldvstar@gmail.com',
'This payment is for the invoice number . ' . $billNumber,
$amount,
$billNumber,
$bank_code,
true
);
$payment_reference = $billPlzBill->id;
}
else if ($payment_method === PaymentMethodType::WALLET) {
/** @var Wallet $wallet */
$wallet = $company_module->wallets()->first();
// if((float) number_format(($wallet->amount - $amount),2) < 0){
// throw new MalformedRequestException('Insufficient wallet balance. Please Top up your wallet.');
// }
$walletPaymentBillNumber = $this->generatesTransactionBillNumber->execute('PYMT-');
$transaction_object = new TransactionObject($walletPaymentBillNumber, TransactionType::PAYMENT, 1, $company_module->id, 1, PaymentMethodType::WALLET, $amount, $amount, 1, 1, 1, 0, 0, null, ApprovalStatus::APPROVED, [], '');
$transaction = $this->createsTransactionableTransaction->execute($wallet, $transaction_object);
$transaction->created_at = $date;
$transaction->updated_at = $date;
$transaction->save();
$payment_reference = $walletPaymentBillNumber;
$this->updatesWalletBalance->execute($wallet, ($amount * -1));
if($run)
{
$packingList = $invoice->owner;
$order = $packingList->owner;
$packingList->status = ApprovalStatus::APPROVED;
$packingList->save();
if(app()->environment('production')){
$this->updateDoFromVTPortalProcessor->execute($packingList);
$this->updateDoFromYDPortalProcessor->execute($packingList);
}
}
// later use this variabke to create a approved payment transaction
$approvalStatus = ApprovalStatus::APPROVED;
// update invoice to completed
if($run){
$this->updatesTransactionStatus->execute($invoice, ApprovalStatus::COMPLETED);
}
}
else {
$payment_method = PaymentMethodType::CASH;
}
$object = new TransactionObject(
$billNumber,
TransactionType::PAYMENT,
$company_module->id,
1,
1,
$payment_method,
$amount,
$amount,
1,
1,
0,
0,
0,
null,
$approvalStatus,
null,
$payment_reference
);
$payment_transaction = $this->createsPaymentTransaction->execute($invoice, $object);
return $payment_transaction;
}
}
@@ -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);
@@ -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,
@@ -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);
@@ -35,11 +35,6 @@ class CreatesTransaction extends AbstractUpdateRelationshipRecord
$model->expires_on = $object->getExpiresOn();
$model->status = $object->getStatus();
if((int)$object->getTransactionType() === TransactionType::SHIPPING_INVOICE){
$model->created_at = Carbon::now()->subDays(10);
$model->updated_at = Carbon::now()->subDays(10);
}
return $this->handler($packing_list->transactions(), $model);
}
}
@@ -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';
}
+14 -7
View File
@@ -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);
}
}
@@ -55,11 +55,12 @@ class OneTimeTransactionFixBillplzFailedCallback extends Command
$this->outputArray = [];
$start = new Carbon();
//This transaction, 15205 has approve payment but not its owner, shipping invoice
$transaction = Transaction::whereIn('id', [15205])->first();
$this->info(Carbon::now() . ' : One time fix failled callback from billplz for transaction with id 15205 cron started.');
//Transaction fix with this one time fix command: 15205, 16803
//This transaction, 16803 has approve payment but not its owner, shipping invoice
$transaction = Transaction::whereIn('id', [16803])->first();
$this->info(Carbon::now() . ' : One time fix failled callback from billplz for transaction with id 16803 cron started.');
if($transaction && $transaction->id == 15205){
if($transaction && $transaction->id == 16803){
$status = ApprovalStatus::APPROVED;
$this->callbackBillplzProcessor->execute($transaction, $status);
@@ -68,6 +69,6 @@ class OneTimeTransactionFixBillplzFailedCallback extends Command
$end = new Carbon();
$elapsedTime = $start->diff($end)->format('%H:%I:%S');
$this->info(Carbon::now() . ' : One time fix failled callback from billplz for transaction with id 15205 cron ended. ElapsedTime: ' . $elapsedTime);
$this->info(Carbon::now() . ' : One time fix failled callback from billplz for transaction with id 16803 cron ended. ElapsedTime: ' . $elapsedTime);
}
}
+2 -1
View File
@@ -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())
];
@@ -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';
+1 -1
View File
@@ -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;
@@ -27,7 +28,9 @@ class TransactionWithStorageResource extends JsonResource
$groupPaymentAttemptsFiltered = [];
$group_payment_expired = null;
$group_payment_history = null;
$group_payment_history_query = null;
$groupTotalAmount = 0;
$payment_history = null;
if ($this->owner instanceof Transaction) {
if ($this->owner) {
@@ -43,7 +46,8 @@ class TransactionWithStorageResource extends JsonResource
if($this->groups){
$group_payment_attempts = GroupForOrderV2Resource::collection($this->groups->whereNotIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]));
$group_payment_expired = GroupForOrderV2Resource::collection($this->groupsWithTrashed->whereIn('status', [ApprovalStatus::EXPIRED]));
$group_payment_history = GroupForOrderV2Resource::collection($this->groups->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::REJECTED]));
$group_payment_history_query = $this->groups->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::REJECTED]);
$group_payment_history = GroupForOrderV2Resource::collection($group_payment_history_query);
}
} else {
@@ -54,9 +58,13 @@ class TransactionWithStorageResource extends JsonResource
}
$packingListReference = null;
if ($this->owner instanceof PackingList) {
$packingListReference = $this->owner->reference;
}
$ts = $this->groups->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION])->last();
if ($ts) {
if ($ts && $group_payment_history && $group_payment_attempts) {
$paymentTransaction = Transaction::where('payment_reference', $ts->reference)->whereIn('status', [ApprovalStatus::PENDING_SUBMISSION])->first();
if($paymentTransaction){
$groupTotalAmount = (double) $this->amount;
@@ -76,6 +84,21 @@ class TransactionWithStorageResource extends JsonResource
}
$payment_history = TransactionResource::collection($this->transactions()
->payments()
->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::COMPLETED, ApprovalStatus::REJECTED])
->get());
//For 'Your Payment Proof' at frontend
if($group_payment_history_query && count($group_payment_history_query) > 0){
if($this->getReferenceForGroupPayment($group_payment_history_query)){
foreach ($payment_history as $item) {
$item['payment_reference'] = $this->getReferenceForGroupPayment($group_payment_history_query);
}
}
}
return [
'id' => $this->id,
'owner_type' => $this->owner_type,
@@ -112,13 +135,9 @@ class TransactionWithStorageResource extends JsonResource
->payments()->where('status', ApprovalStatus::EXPIRED)
->get()
),
'payment_history' => TransactionResource::collection(
$this->transactions()
->payments()
->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::COMPLETED, ApprovalStatus::REJECTED])
->get()
),
'payment_history' => $payment_history,
'remarks' => RemarkResource::collection($this->remarks),
'packing_list_reference' => $packingListReference,
'storages' => $this->storages ? $this->storages : null, //from middleware
'is_waived' => (int) $this->is_waived,
'expires_on' => Carbon::parse($this->expires_on)->format('d-m-Y h:i:s A'),
@@ -126,4 +145,12 @@ class TransactionWithStorageResource extends JsonResource
'created_at' => Carbon::parse($this->created_at)->format('d-m-Y')
];
}
private function getReferenceForGroupPayment($groups){
if(count($groups)){
$firstGroup = $groups[0];
return $firstGroup['reference'];
}
return null;
}
}
+8
View File
@@ -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');
}
}
@@ -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');
});
}
}
+1
View File
@@ -31,6 +31,7 @@
"vue": "^2.6.10",
"vue-avatar": "^2.1.8",
"vue-debounce": "^2.6.0",
"vue-multi-select": "^4.6.0",
"vue-template-compiler": "^2.6.10",
"vue-the-mask": "^0.11.1",
"vuelidate": "^0.7.4",
@@ -71,6 +71,43 @@
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="row m-b-15">
<div class="col-12 col-md pr-md-1 pb-3 pb-md-0">
<validation-wrapper-component :validator="$v.parameters.pickup_time">
<label>收货时间 Available Hours</label>
<input type="time" class="form-control" name="pickup_time" v-model="parameters.pickup_time">
</validation-wrapper-component>
</div>
<div class="col-12 col-md pl-md-1">
<validation-wrapper-component :validator="$v.parameters.latest_pickup_time">
<label>最晚收货时间 Latest Available Hours</label>
<input type="time" class="form-control" name="latest_pickup_time" v-model="parameters.latest_pickup_time">
</validation-wrapper-component>
</div>
</div>
<div class="row m-b-15">
<div class="col-12 col-md pr-md-1 pb-3 pb-md-0">
<validation-wrapper-component selectable class="m-b-15" :validator="$v.parameters.property_type">
<label class="text-primary">房型 Receiver's Property Type</label>
<select-component :options="propertyOptions" v-model="parameters.property_type"></select-component>
</validation-wrapper-component>
</div>
<div class="col-12 col-md pl-md-1 ">
<tools-required-component></tools-required-component>
</div>
</div>
<div class="col no-padding">
<div class="row">
<div class="col"></div>
<div class="col-12 col-sm-7">
<h6 class="text-right fs-12 text-danger m-b-15 text-right">**kindly reply within 2 hours while warehouse contact to arrange for delivery, otherwise, reschedule of delivery date will apply.</h6>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row" v-if="[7,8].includes($store.getters.getCompanyModuleType)">
@@ -174,8 +211,19 @@
remark: '',
phone: '',
person_in_charge: '',
}
pickup_time: '',
latest_pickup_time: '',
property_type: '',
tools_required: '',
},
propertyOptions: [
{ id: 1, text: '住家-Landed house' },
{ id: 2, text: '公寓-Condominium (Drop on lobby only)' },
{ id: 3, text: '工厂-Factory' },
{ id: 4, text: '店面-Shop' },
{ id: 5, text: '商场-Shopping Mall (Drop on loading bay only)' },
{ id: 6, text: 'Others' },
],
}
},
created(){
@@ -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>
@@ -116,9 +116,10 @@
},
sumAmount () {
var new_object = this.selectedInvoice;
return Object.keys(new_object).reduce(function(total, key) {
return total + Math.round(new_object[key].amount * 100) / 100;
var total = Object.keys(new_object).reduce(function(total, key) {
return total + new_object[key].amount;
}, 0).toFixed(2);
return Math.round(total * 100) / 100;
},
selectedIds () {
return this.selectedInvoice.map(s=>s.id);
@@ -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>
@@ -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, Im 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>
@@ -74,9 +74,6 @@
data(){
return {
filters: this.options,
pollingInterval: null,
isPolling: false,
isFetchingResult: false,
isLoading: false,
}
},
@@ -87,13 +84,26 @@
computed: {
pendingList () {
return this.$store.getters.isInCompleteQueue(this.section);
}
},
getJob() {
return this.$store.getters.getJob(this.section);
},
getJobAttemptCount() {
return this.$store.getters.getJobAttemptCount(this.section);
},
},
watch: {
pendingList(inComplete){
if(inComplete){
this.fetchList();
}
},
getJobAttemptCount(newValue, oldValue) {
// console.log('Old value:', JSON.stringify(oldValue));
// console.log('New value:', JSON.stringify(newValue));
if(this.getJob){
this.fetchJobResult(this.getJob.isLastAttempt);
}
}
},
methods: {
@@ -101,7 +111,7 @@
let listDecorators = this.$store.getters.getListDetails(this.section);
let url = this.endpoint + '?page=' + listDecorators.page + '&filters=' + JSON.stringify(listDecorators.filters);
this.isLoading = true;
this.submitJob(url);
this.$store.dispatch('submitJobRequest', {'url': url, 'name': this.section});
},
successHandler(response){
let result = JSON.parse(response.payload.data.result);
@@ -118,83 +128,21 @@
to: result.meta.to,
total: result.meta.total
};
this.stopPolling();
this.$store.dispatch('completeList', {'name': this.section, 'data': result.data});
this.$store.dispatch('stopPollingJobResultByJobId', {'jobId': this.getJob.jobId});
this.$refs.pagination.makePagination(result.meta, result.links);
this.isLoading = false;
},
errorHandler(error){
this.isFetchingResult = false;
this.isPolling = false;
// console.log("Error: " + JSON.stringify(error));
this.$store.dispatch('updatePollingJobResultByJobId', {'jobId': this.getJob.jobId, 'isPolling': false, 'isFetchingResult': false });
},
startPolling(jobId, maxAttempts = 8) {
let attempts = 0;
let interval = 10000; // Initial interval
const resetPollingInterval = (customInterval) => {
this.pollingInterval = setInterval(pollJobResult, customInterval);
};
const pollJobResult = () => {
if (this.isPolling || this.isFetchingResult) {
return;
}
this.isPolling = true;
attempts++;
if(attempts === 1){
this.stopPolling();
resetPollingInterval(5000);
}
if (attempts > maxAttempts) {
this.stopPolling();
this.isLoading = false;
console.log(`Reached maximum attempts (${maxAttempts}). Polling stopped.`);
return;
}
if(attempts === maxAttempts){
this.fetchJobResult(jobId, true);
}
else{
this.fetchJobResult(jobId);
}
};
// pollJobResult(); // Initial call
this.pollingInterval = setInterval(pollJobResult, interval);
},
stopPolling() {
clearInterval(this.pollingInterval);
this.pollingInterval = null;
this.isPolling = false;
this.isFetchingResult = false;
},
submitJob(url){
fetchJobResult(isLastAttempt = false) {
this.$store.dispatch('updatePollingJobResultByJobId', {'jobId': this.getJob.jobId, 'isFetchingResult': true });
try {
this.$store.dispatch('crudRequestV2', {endpoint: url, method: 'get'}).then(response => {
let success = response.ok;
response.json().then(response => {
if(!success){return;}
let jobId = response.payload.data.job_id;
if(jobId){
this.startPolling(jobId);
}
});
})
} catch (error) {
console.error('Error submitJob', error);
}
},
fetchJobResult(jobId, isLastAttempt = false) {
// console.log('fetchJobResult: ', jobId);
this.isFetchingResult = true;
try {
let anotherEndpoint = route('api.job.fetch', jobId);
let anotherEndpoint = route('api.job.fetch', this.getJob.jobId);
if(isLastAttempt){
anotherEndpoint = route('api.job.fetch.last.attempt', jobId, isLastAttempt);
anotherEndpoint = route('api.job.fetch.last.attempt', this.getJob.jobId, isLastAttempt);
}
this.poll(anotherEndpoint, 'get', this.section, false, false); //cief todo: Uncaught (in promise) null
} catch (error) {
@@ -0,0 +1,59 @@
<template>
<div>
<label class="text-primary">卸货工具 Tools required to unload goods</label>
<vue-multi-select
ref="multiSelect"
v-model="values"
:options="options"
:btnLabel="btnLabel"
@open="open"
@close="close"
:selectOptions="data">
<template v-slot:option="{ option }">
<input type="checkbox" :checked="option.selected"/>
<span>{{ option.name }}</span>
</template>
</vue-multi-select>
</div>
</template>
<script>
import vueMultiSelect from 'vue-multi-select';
import 'vue-multi-select/dist/lib/vue-multi-select.css';
export default {
data() {
return {
values: [],
data: [{
list: [
{ name: 'Manpower' },
{ name: 'Forklift' },
{ name: 'None of the above' }
],
}],
options: {
multi: true,
groups: true,
},
};
},
methods: {
open() {
console.log('open');
},
close() {
console.log('close');
},
btnLabel(values) {
if (values.length === 0) {
return 'Select Tools required';
}
return values.map(v => v.name).join(', ');
},
},
components: {
vueMultiSelect,
},
};
</script>
@@ -5,10 +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="this.$qr_code_img_url + 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>
@@ -17,7 +17,7 @@
<div class="col-auto hide" v-if="$store.getters.isSuperAdmin">
<button type="button" class="btn b-rad-none btn-danger fs-11 requestModal" data-type="deletePackingList"><i class="fa fa-times text-white fs-12"></i></button>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="deletePackingList">
<delete-packinglist-form-component :data="data"></delete-packinglist-form-component>
<delete-packinglist-form-component :data="data" :section="section"></delete-packinglist-form-component>
</modal-component>
<button type="button" class="btn b-rad-none btn-primary fs-11 requestModal" data-type="claimPackingList">Claim</button>
</div>
@@ -51,7 +51,7 @@
<div class="btn btn-sm btn-success btn-block b-rad-none" data-dismiss="modal">Cancel</div>
</div>
<div class="col p-l-5">
<div class="btn btn-sm btn-danger btn-block b-rad-none" data-dismiss="modal" @click="submit(route('api.packing_list.delete', item.id), 'delete', 'unclaimedPackingListSection', true, true)">Confirm</div>
<div class="btn btn-sm btn-danger btn-block b-rad-none" data-dismiss="modal" @click="submit(route('api.packing_list.delete', item.id), 'delete', section, true, true)">Confirm</div>
</div>
</div>
</div>
@@ -78,6 +78,12 @@
<script>
import componentHandler from '../../../general/mixins/componentHandler';
export default {
mixins: [componentHandler]
mixins: [componentHandler],
data() {
return {
isLoading: false,
section: 'unclaimedPackingListSection',
}
}
}
</script>
@@ -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>
@@ -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>
@@ -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(){
@@ -157,6 +157,13 @@
</div>
</a>
</div>
<div class="row no-margin" v-if="item.payment_method === 4 && item.payment_reference">
<a :href="route('billplz.bill', item.payment_reference)" target="_blank">
<div class="icon-thumbnail fs-11 text-white icon-25 bg-primary btn-rounded float-left m-r-5">
<i class="fa fa-file-image-o fs-10"></i>
</div>
</a>
</div>
</div>
</div>
</div>
@@ -181,9 +188,13 @@
},
methods: {
clickExpand(){
if(this.item
&& ((this.item.payment_method !== 5 && this. item.documents.length)
|| (this.item.payment_method === 5 && (this.item.status === 2 || this.item.status === 3)))){
// if(this.item
// && ((this.item.payment_method !== 5 && this. item.documents.length)
// || (this.item.payment_method === 5 && (this.item.status === 2 || this.item.status === 3)))){
// this.expandPaymentDetails = !this.expandPaymentDetails;
// }
if(this.item){
this.expandPaymentDetails = !this.expandPaymentDetails;
}
},
@@ -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>
@@ -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: {
@@ -157,6 +157,7 @@
this.error = response.payload.data.message;
}
else{
this.closeModal();
this.updateList();
}
}
@@ -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>
@@ -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>
@@ -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">
@@ -19,6 +19,10 @@ export default {
remark: {},
phone: {required, numeric},
person_in_charge: { required },
pickup_time: { required },
latest_pickup_time: { required },
property_type: {},
tools_required: {},
}
},
mixins: [addressFormHandler]
+134
View File
@@ -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 });
}
}
}
+3 -1
View File
@@ -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
}
})
+10 -4
View File
@@ -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>
@@ -131,7 +131,7 @@
</div>
</div>
</div>
<div class="row">
<div class="row" v-if="$store.getters.isAdmin">
<div class="col">
<admin-payments-billing-polling-section-component></admin-payments-billing-polling-section-component>
</div>
@@ -0,0 +1,21 @@
@extends('layouts.base_pdf')
@section('inner_content')
<br>
<htmlpageheader name="page-header">
<br><br>
<div class="separator"><strong><i>{{ $invoice_transaction->bill_no }}</i></strong></div>
</htmlpageheader>
@include('pages.pdfs.shipping_invoice_sst_inner', ['invoice_transaction' => $invoice_transaction])
<pagebreak />
@include('pages.pdfs.packing_list_measurement', ['invoice_transaction' => $invoice_transaction])
<htmlpagefooter name="page-footer">
<table width="100%">
<tr>
<td style="text-align: right; ">SST This is generated by computer. No signature required.</td>
<td style="text-align: right; ">Page {PAGENO} of {nbpg}</td>
</tr>
</table>
</htmlpagefooter>
@endsection
@@ -0,0 +1,143 @@
<style>
body {
font-size: 14px;
}
</style>
<table>
<tr>
<td class="header-logo">
<img src="{{ asset('images/ri_1.png') }}" alt="logo" id="logo" class="logo">
</td>
<td class="header-cief-address">
<span class="company-name">
<strong>
CIEF WORLDWIDE SDN BHD
</strong>
</span>
<span class="company-reg">(1134596-M)</span><br>
No. 72-3, Jalan Jalil 1,<br>
The Earth Bukit Jalil,<br>
57000 Kuala Lumpur<br>
Tel: 03-8082 1252<br>
SST No: W10-2403-32000643
</td>
<td class="header-details">
<div class="title" style="font-size: 20px; text-transform: uppercase;">
<strong>
Invoice
</strong>
</div>
<div class="number">Invoice No: {{ $invoice_transaction->bill_no }}</div>
@php
$companyModule = $invoice_transaction->owner->owner->companyModule;
@endphp
<div class="date">Date: {{ $invoice_transaction->created_at }}</div>
<div class="ref">Order No: {{ $invoice_transaction->owner->owner->reference }}</div>
<div class="ref">Container Ref: {{ $invoice_transaction->owner->containers()->first()->reference }}</div>
{{--<div class="d-none">{{ $companyModule->inviters()->withPivot('invitee_reference')->first()->pivot->invitee_reference }}</div>--}}
<div>&nbsp;</div>
</div>
</td>
</tr>
<tr>
<td colspan="3" class="bill-to">
<span class="sub-title">
Bill To
</span>
</td>
</tr>
<tr>
<td colspan="3" class="address">
<div class="label">
{{ $companyModule->name }}
</div>
<div class="address">
@php
$addresses = $companyModule->addresses()->where('status', '=', \App\Classes\ValueObjects\Constants\ApprovalStatus::APPROVED)->where('type', '=', \App\Classes\ValueObjects\Constants\AddressType::BILLING)->first();
@endphp
@if($addresses)
{{ $addresses->street_one }}
{{ $addresses->street_two }} ,
{{ $addresses->district()->first()->name }},
{{ $addresses->postcode }}
{{ $addresses->state()->first()->name }},
{{ $addresses->country()->first()->name }}
@endif
</div>
<div>
@php
$contact = $companyModule->contacts()->first();
@endphp
Phone: {{ $contact ? $contact->phone : '' }}
</div>
</td>
</tr>
</table>
<br>
<br>
<table class="line-table" style="overflow: wrap" autosize="1">
<thead>
<tr>
<th width="5%">No</th>
<th class="description">Description</th>
<th width="10%">Qty</th>
<th width="10%">Unit Price <br>(RM)</th>
<th width="10%">Tax (%)</th>
<th width="20%">Tax Amount <br>(RM)</th>
<th width="15%">Sub Total<br>(RM)</th>
</tr>
</thead>
<tbody>
@foreach ($invoice_transaction->transactionDetails as $key => $transaction_detail)
<tr>
<td width="5%" class="center top">{{ $key + 1 }}</td>
<td class="description">{!! $transaction_detail->name !!}</td>
<td width="10%" class="center top" style="text-align: center">{{ round($transaction_detail->quantity, 3) }}</td>
<td width="10%" class="center top" style="text-align: center">
{{ round($transaction_detail->price, 2) }}
</td>
<td width="10%" class="center top" style="text-align: center">
{{ round($transaction_detail->tax_percentage, 2) }}
</td>
<td width="20%" class="center top" style="text-align: center">
{{ number_format(round($transaction_detail->tax_amount, 2), 2) }}
</td>
<td width="15%" class="right top">
{{ number_format(round($transaction_detail->amount, 2), 2) }}
</td>
</tr>
@endforeach
</tbody>
<tfoot>
<tr class="subtotal">
<td colspan="5"></td>
<td class="right middle">Subtotal</td>
<td class="right middle">
{{ number_format(round($invoice_transaction->amount - $invoice_transaction->tax, 2), 2) }}
</td>
</tr>
<tr class="billingcharges">
<td colspan="5"></td>
<td class="right">Service Charges</td>
<td class="right">
{{ number_format(round($invoice_transaction->service_charge, 2), 2) }}
</td>
</tr>
<tr class="billingcharges">
<td colspan="5"></td>
<td class="right">Total SST (6%) RM</td>
<td class="right">{{ number_format($invoice_transaction->tax, 2) }}</td>
</tr>
<tr>
<td colspan="5"></td>
<td class="right middle">Total Amount RM</td>
<td class="total right middle">
{{ number_format(round($invoice_transaction->amount, 2), 2) }}
</td>
</tr>
</tfoot>
</table>
@@ -0,0 +1,163 @@
@extends('layouts.base_pdf')
@section('inner_content')
@php
$grandTotal = 0;
$grandTotalTax = 0;
$grandSubTotal = 0;
@endphp
<table>
<tr>
<td class="header-logo">
<img src="{{ asset('images/ri_1.png') }}" alt="logo" id="logo" class="logo">
</td>
<td class="header-cief-address">
<span class="company-name">
<strong>
CIEF WORLDWIDE SDN BHD
</strong>
</span>
<span class="company-reg">(1134596-M)</span><br>
No. 72-3, Jalan Jalil 1,<br>
The Earth Bukit Jalil,<br>
57000 Kuala Lumpur<br>
Tel: 03-8082 1252<br>
SST No: W10-2403-32000643
</td>
<td class="header-details">
<div class="title" style="font-size: 20px; text-transform: uppercase;">
<strong>
Summary
</strong>
</div>
@php
$companyModule = $invoice_transactions[0]->owner->owner->companyModule;
@endphp
{{-- <div class="date">Date: {{ $invoice_transactions[0]->created_at }}</div> --}}
<div class="date">Date: {{ \Carbon\Carbon::now() }}</div>
<div>&nbsp;</div>
</div>
</td>
</tr>
<tr>
<td colspan="3" class="bill-to">
<span class="sub-title">
Bill To
</span>
</td>
</tr>
<tr>
<td colspan="3" class="address">
<div class="label">
{{ $companyModule->name }}
</div>
<div class="address">
@php
$addresses = $companyModule->addresses()->where('status', '=', \App\Classes\ValueObjects\Constants\ApprovalStatus::APPROVED)->where('type', '=', \App\Classes\ValueObjects\Constants\AddressType::BILLING)->first();
@endphp
{{ $addresses->street_one }}
{{ $addresses->street_two }} ,
{{ $addresses->district()->first()->name }},
{{ $addresses->postcode }}
{{ $addresses->state()->first()->name }},
{{ $addresses->country()->first()->name }}
</div>
<div>
@php
$contact = $companyModule->contacts()->first();
@endphp
Phone: {{ $contact ? $contact->phone : '' }}
</div>
</td>
</tr>
</table>
<br>
<br>
<table class="line-table" style="overflow: wrap" autosize="1">
<thead>
<tr>
<th width="5%">No</th>
<th class="description">Invoice No</th>
<th class="description">Description</th>
<th width="10%">Qty</th>
<th width="10%">Unit Price <br>(RM)</th>
<th width="10%">Tax (%)</th>
<th width="20%">Tax Amount <br>(RM)</th>
<th width="15%">Sub Total<br>(RM)</th>
</tr>
</thead>
<tbody>
@foreach ($invoice_transactions as $key => $invoice_transaction)
@foreach ($invoice_transaction->transactionDetails as $transaction_detail)
<tr>
<td width="5%" class="center top">{{ $key + 1 }}</td>
<td width="15%" class="center top">{{ $invoice_transaction->bill_no }}</td>
<td class="description">{!! $transaction_detail->name !!}</td>
<td width="10%" class="center top" style="text-align: center">{{ round($transaction_detail->quantity, 3) }}</td>
<td width="10%" class="center top" style="text-align: center">
{{ round($transaction_detail->price, 2) }}
</td>
<td width="10%" class="center top" style="text-align: center">
{{ round($transaction_detail->tax_percentage, 2) }}
</td>
<td width="20%" class="center top" style="text-align: center">
{{ number_format(round($transaction_detail->tax_amount, 2), 2) }}
</td>
<td width="15%" class="right top">
{{ round($transaction_detail->amount, 2) }}
</td>
</tr>
@endforeach
@php
$grandSubTotal = $grandSubTotal + round($invoice_transaction->amount - $invoice_transaction->tax, 2);
$grandTotalTax = $grandTotalTax + round($invoice_transaction->tax, 2);
$grandTotal = $grandTotal + round($invoice_transaction->amount, 2);
@endphp
@endforeach
</tbody>
<tfoot>
<tr class="subtotal">
<td colspan="6"></td>
<td class="right middle">Total Taxable Amount</td>
<td class="right middle">
{{ round($grandSubTotal, 2) }}
</td>
</tr>
<tr class="billingcharges">
<td colspan="6"></td>
<td class="right middle">Total SST (6%) RM</td>
<td class="right middle">
{{ round($grandTotalTax, 2) }}
</td>
</tr>
<tr>
<td colspan="6"></td>
<td class="right middle">Total Amount RM</td>
<td class="total right middle">
{{ round($grandTotal, 2) }}
</td>
</tr>
</tfoot>
</table>
@foreach ($invoice_transactions as $transaction)
<pagebreak />
@include('pages.pdfs.shipping_invoice_sst_inner', ['invoice_transaction' => $transaction])
<pagebreak />
@include('pages.pdfs.packing_list_measurement', ['invoice_transaction' => $transaction])
@endforeach
<htmlpagefooter name="page-footer">
<table width="100%">
<tr>
<td style="text-align: right; ">This is generated by computer. No signature required.</td>
<td style="text-align: right; ">Page {PAGENO} of {nbpg}</td>
</tr>
</table>
</htmlpagefooter>
@endsection
@@ -0,0 +1,134 @@
<div class="row">
<div class="col b-r b-white">
<div class="row fs-12 text-center">
<div class="col p-t-20 p-b-20 bg-master-lighter tabButton @if($active==1) active @endif" tab-name="segment1">
<div class="row justify-content-center m-b-5">
<div class="col-auto">
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="35" height="35" viewBox="0 0 172 172" style=" fill:#000000;">
<defs>
<linearGradient x1="66.87575" y1="36.02325" x2="66.87575" y2="164.11756" gradientUnits="userSpaceOnUse" id="color-1_hUqtl21qkZmg_gr1">
<stop offset="0" stop-color="#009add"></stop>
<stop offset="1" stop-color="#00baa4"></stop>
</linearGradient>
<linearGradient x1="105.12425" y1="35.4535" x2="105.12425" y2="164.77331" gradientUnits="userSpaceOnUse" id="color-2_hUqtl21qkZmg_gr2">
<stop offset="0" stop-color="#009add"></stop>
<stop offset="1" stop-color="#00baa4"></stop>
</linearGradient>
<linearGradient x1="86" y1="130.00781" x2="86" y2="146.81275" gradientUnits="userSpaceOnUse" id="color-3_hUqtl21qkZmg_gr3">
<stop offset="0" stop-color="#4ec9ff"></stop>
<stop offset="1" stop-color="#2bffe6"></stop>
</linearGradient>
<linearGradient x1="86" y1="2.6875" x2="86" y2="163.9375" gradientUnits="userSpaceOnUse" id="color-4_hUqtl21qkZmg_gr4">
<stop offset="0" stop-color="#009add"></stop>
<stop offset="1" stop-color="#00baa4"></stop>
</linearGradient>
</defs>
<g fill="none" fill-rule="nonzero" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="none" font-weight="none" font-size="none" text-anchor="none" style="mix-blend-mode: normal">
<path d="M0,172v-172h172v172z" fill="none"></path>
<g>
<path d="M73.43863,107.5c-3.30294,0 -6.03075,2.40531 -6.48763,5.53087h-0.1505c-0.45687,-3.12556 -3.182,-5.53087 -6.48763,-5.53087c-3.62544,0 -6.56287,2.88906 -6.56287,6.45269c0,7.2885 6.78325,12.19856 10.59681,14.37812c1.55606,0.88956 3.49913,0.88956 5.05519,0c3.81625,-2.18225 10.59681,-7.08962 10.59681,-14.37812c0,-3.56363 -2.93744,-6.45269 -6.56019,-6.45269z" fill="url(#color-1_hUqtl21qkZmg_gr1)"></path>
<path d="M111.68713,107.5c-3.30294,0 -6.03075,2.40531 -6.48762,5.53087h-0.1505c-0.45419,-3.12556 -3.182,-5.53087 -6.48763,-5.53087c-3.62275,0 -6.56288,2.88906 -6.56288,6.45269c0,7.2885 6.78325,12.19856 10.59681,14.37813c1.55606,0.88956 3.49913,0.88956 5.05519,0c3.81625,-2.17956 10.5995,-7.08694 10.5995,-14.37812c0,-3.56363 -2.93744,-6.45269 -6.56288,-6.45269z" fill="url(#color-2_hUqtl21qkZmg_gr2)"></path>
<path d="M75.25,134.375c0,5.93669 4.81331,10.75 10.75,10.75c5.93669,0 10.75,-4.81331 10.75,-10.75v-2.6875h-21.5z" fill="url(#color-3_hUqtl21qkZmg_gr3)"></path>
<path d="M139.75,95.90344v-6.74831c0.02956,-0.15856 0.09406,-0.301 0.09406,-0.46762l-0.00806,-22.12619c0.2795,-14.89412 -7.39331,-27.3695 -10.70431,-32.04038c-5.54431,-7.80719 -11.05906,-11.73631 -13.83525,-12.08569c-1.06156,-0.12362 -2.11775,0.387 -2.65794,1.31688l-1.14487,1.97262c-0.97019,1.67431 -2.71169,2.67406 -4.65475,2.67406c-1.94306,0 -3.68994,-0.99975 -4.66012,-2.67406l-11.98625,-20.63194c-0.87613,-1.505 -2.44563,-2.40531 -4.1925,-2.40531c-1.74956,0 -3.31906,0.90031 -4.18981,2.408l-11.94056,20.54863c-0.97019,1.67431 -2.71169,2.67406 -4.65475,2.67406c-1.94306,0 -3.68994,-0.99975 -4.66281,-2.67406l-1.16906,-2.01025c-0.42463,-0.73369 -1.17712,-1.2255 -2.021,-1.31956c-2.64181,-0.3225 -7.47662,3.06375 -11.86531,8.38231c-6.26456,7.60025 -13.01019,20.86575 -13.15262,35.31375l-0.09406,22.66638c0,0 0,0 0,0.00269c0,0.00269 0,0.00538 0,0.00806v7.21594c-6.34519,3.02881 -10.75,9.48687 -10.75,16.97156c0,10.37106 8.44144,18.8125 18.8125,18.8125h0.12362c6.64888,18.77487 24.51,32.25 45.56388,32.25c21.05388,0 38.915,-13.47513 45.56388,-32.25h0.12363c10.37106,0 18.8125,-8.44144 18.8125,-18.8125c0,-7.48469 -4.40481,-13.94275 -10.75,-16.97156zM49.6435,34.11513c2.7735,-3.36475 4.94769,-5.02025 6.24038,-5.80769l0.0215,0.03762c1.94844,3.34863 5.42875,5.34813 9.3095,5.34813c3.88344,0 7.36106,-1.9995 9.30412,-5.35081l11.481,-19.76388l11.52669,19.84719c1.94844,3.34863 5.42875,5.34813 9.3095,5.34813c3.82969,0 7.267,-1.94844 9.22619,-5.21375c1.83019,1.20937 5.01756,3.90763 8.686,9.07031c2.28975,3.23038 9.59975,14.61463 9.69919,27.93119c-8.66719,-18.07881 -27.09538,-30.62406 -48.44756,-30.62406c-21.16406,0 -39.45788,12.32487 -48.21644,30.14838c0.4085,-12.65544 6.321,-24.252 11.85994,-30.97075zM26.875,112.875c0,-6.48763 4.62519,-11.91637 10.75,-13.16606v5.59806c-3.12556,1.10994 -5.375,4.0635 -5.375,7.568c0,3.59856 2.37306,6.60856 5.62763,7.64594c0.19619,1.91887 0.53481,3.79206 0.94869,5.64106c-6.70263,-0.74981 -11.95131,-6.3855 -11.95131,-13.287zM129,115.5625c0,23.70913 -19.29087,43 -43,43c-23.70913,0 -43,-19.29087 -43,-43v-16.125h8.0625c9.34981,0 17.47413,-5.32931 21.5,-13.11231c4.02587,7.783 12.15019,13.11231 21.5,13.11231h34.9375zM94.0625,94.0625c-10.37106,0 -18.8125,-8.44144 -18.8125,-18.8125v-2.6875h-5.375v2.6875c0,10.37106 -8.44144,18.8125 -18.8125,18.8125h-13.4375v-5.36425v-0.01075c0,-26.67344 21.70156,-48.375 48.375,-48.375c26.67344,0 48.375,21.70156 48.375,48.375v5.375zM133.17369,126.162c0.41387,-1.84631 0.75519,-3.7195 0.94869,-5.64106c3.25456,-1.03737 5.62762,-4.04738 5.62762,-7.64594c0,-3.5045 -2.24944,-6.45806 -5.375,-7.568v-5.59806c6.12481,1.24969 10.75,6.67575 10.75,13.16606c0,6.9015 -5.24869,12.53719 -11.95131,13.287z" fill="url(#color-4_hUqtl21qkZmg_gr4)"></path>
</g>
</g>
</svg>
</div>
</div>
<div class="row">
<div class="col">
<div class="fs-12 m-t-5 all-caps">{{ __('Standard') }}</div>
</div>
</div>
</div>
</div>
</div>
<div class="col b-r b-white">
<div class="row fs-12 text-center">
<div class="col p-t-20 p-b-20 bg-master-lighter tabButton @if($active==2) active @endif" tab-name="segment2">
<div class="row justify-content-center m-b-5">
<div class="col-auto">
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="35" height="35" viewBox="0 0 172 172" style=" fill:#000000;">
<defs>
<linearGradient x1="104.8125" y1="95.74219" x2="104.8125" y2="114.9175" gradientUnits="userSpaceOnUse" id="color-1_TUOBhQt-Vj1j_gr1">
<stop offset="0" stop-color="#4ec9ff"></stop>
<stop offset="1" stop-color="#2bffe6"></stop>
</linearGradient>
<linearGradient x1="67.1875" y1="95.74219" x2="67.1875" y2="114.9175" gradientUnits="userSpaceOnUse" id="color-2_TUOBhQt-Vj1j_gr2">
<stop offset="0" stop-color="#4ec9ff"></stop>
<stop offset="1" stop-color="#2bffe6"></stop>
</linearGradient>
<linearGradient x1="86" y1="125.40413" x2="86" y2="133.41288" gradientUnits="userSpaceOnUse" id="color-3_TUOBhQt-Vj1j_gr3">
<stop offset="0" stop-color="#4ec9ff"></stop>
<stop offset="1" stop-color="#2bffe6"></stop>
</linearGradient>
<linearGradient x1="86" y1="10.234" x2="86" y2="158.13788" gradientUnits="userSpaceOnUse" id="color-4_TUOBhQt-Vj1j_gr4">
<stop offset="0" stop-color="#009add"></stop>
<stop offset="1" stop-color="#00baa4"></stop>
</linearGradient>
</defs>
<g fill="none" fill-rule="nonzero" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="none" font-weight="none" font-size="none" text-anchor="none" style="mix-blend-mode: normal">
<path d="M0,172v-172h172v172z" fill="none"></path>
<g>
<circle cx="39" cy="39" transform="scale(2.6875,2.6875)" r="3" fill="url(#color-1_TUOBhQt-Vj1j_gr1)"></circle>
<circle cx="25" cy="39" transform="scale(2.6875,2.6875)" r="3" fill="url(#color-2_TUOBhQt-Vj1j_gr2)"></circle>
<rect x="28" y="47" transform="scale(2.6875,2.6875)" width="8" height="3" fill="url(#color-3_TUOBhQt-Vj1j_gr3)"></rect>
<path d="M142.4375,80.11975v-7.55725c0,-31.11856 -25.31625,-56.4375 -56.4375,-56.4375c-31.12125,0 -56.4375,25.31894 -56.4375,56.4375v7.55725c-4.81062,2.79231 -8.0625,7.98994 -8.0625,13.94275c0,8.89294 7.23206,16.125 16.125,16.125h0.13706c1.40556,25.42106 22.47019,45.6875 48.23794,45.6875c25.76775,0 46.83238,-20.26644 48.23794,-45.6875h0.13706c8.89294,0 16.125,-7.23206 16.125,-16.125c0,-5.95281 -3.25188,-11.15044 -8.0625,-13.94275zM34.9375,77.9375v-5.375h16.125c7.40944,0 13.4375,-6.02806 13.4375,-13.4375v-5.375h-5.375v5.375c0,4.44512 -3.61738,8.0625 -8.0625,8.0625h-15.83744c2.69556,-25.63875 24.43475,-45.6875 50.77494,-45.6875c26.34019,0 48.07938,20.04875 50.77494,45.6875h-42.71244c-4.44512,0 -8.0625,-3.61738 -8.0625,-8.0625v-5.375h-5.375v5.375c0,7.40944 6.02806,13.4375 13.4375,13.4375h43v5.375h-46.91837c-8.213,0 -14.89413,-6.68113 -14.89413,-14.89413v-9.29337h-5.375v8.94937c0,8.40113 -6.837,15.23813 -15.23813,15.23813zM26.875,94.0625c0,-5.92863 4.82138,-10.75 10.75,-10.75v8.0625h-2.6875c-1.4835,0 -2.6875,1.20131 -2.6875,2.6875c0,1.48619 1.204,2.6875 2.6875,2.6875h2.6875v8.0625c-5.92862,0 -10.75,-4.82137 -10.75,-10.75zM86,150.5c-23.70912,0 -43,-19.29087 -43,-43v-24.1875h11.63687c7.61906,0 14.28675,-4.15488 17.85575,-10.31731c3.48031,6.15438 10.08888,10.31731 17.6515,10.31731h38.85587v24.1875c0,23.70913 -19.29087,43 -43,43zM134.375,104.8125v-8.0625h2.6875c1.4835,0 2.6875,-1.20131 2.6875,-2.6875c0,-1.48619 -1.204,-2.6875 -2.6875,-2.6875h-2.6875v-8.0625c5.92863,0 10.75,4.82137 10.75,10.75c0,5.92863 -4.82137,10.75 -10.75,10.75z" fill="url(#color-4_TUOBhQt-Vj1j_gr4)"></path>
</g>
</g>
</svg>
</div>
</div>
<div class="row">
<div class="col">
<div class="fs-12 m-t-5 all-caps">{{ __('Custom') }}</div>
</div>
</div>
</div>
</div>
</div>
<div class="col b-r b-white">
<div class="row fs-12 text-center">
<div class="col p-t-20 p-b-20 bg-master-lighter tabButton @if($active==3) active @endif" tab-name="segment3">
<div class="row justify-content-center m-b-5">
<div class="col-auto">
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="35" height="35" viewBox="0 0 172 172" style=" fill:#000000;">
<defs>
<linearGradient x1="104.8125" y1="95.74219" x2="104.8125" y2="114.9175" gradientUnits="userSpaceOnUse" id="color-1_TUOBhQt-Vj1j_gr1">
<stop offset="0" stop-color="#4ec9ff"></stop>
<stop offset="1" stop-color="#2bffe6"></stop>
</linearGradient>
<linearGradient x1="67.1875" y1="95.74219" x2="67.1875" y2="114.9175" gradientUnits="userSpaceOnUse" id="color-2_TUOBhQt-Vj1j_gr2">
<stop offset="0" stop-color="#4ec9ff"></stop>
<stop offset="1" stop-color="#2bffe6"></stop>
</linearGradient>
<linearGradient x1="86" y1="125.40413" x2="86" y2="133.41288" gradientUnits="userSpaceOnUse" id="color-3_TUOBhQt-Vj1j_gr3">
<stop offset="0" stop-color="#4ec9ff"></stop>
<stop offset="1" stop-color="#2bffe6"></stop>
</linearGradient>
<linearGradient x1="86" y1="10.234" x2="86" y2="158.13788" gradientUnits="userSpaceOnUse" id="color-4_TUOBhQt-Vj1j_gr4">
<stop offset="0" stop-color="#009add"></stop>
<stop offset="1" stop-color="#00baa4"></stop>
</linearGradient>
</defs>
<g fill="none" fill-rule="nonzero" stroke="none" stroke-width="1" stroke-linecap="butt" stroke-linejoin="miter" stroke-miterlimit="10" stroke-dasharray="" stroke-dashoffset="0" font-family="none" font-weight="none" font-size="none" text-anchor="none" style="mix-blend-mode: normal">
<path d="M0,172v-172h172v172z" fill="none"></path>
<g>
<circle cx="39" cy="39" transform="scale(2.6875,2.6875)" r="3" fill="url(#color-1_TUOBhQt-Vj1j_gr1)"></circle>
<circle cx="25" cy="39" transform="scale(2.6875,2.6875)" r="3" fill="url(#color-2_TUOBhQt-Vj1j_gr2)"></circle>
<rect x="28" y="47" transform="scale(2.6875,2.6875)" width="8" height="3" fill="url(#color-3_TUOBhQt-Vj1j_gr3)"></rect>
<path d="M142.4375,80.11975v-7.55725c0,-31.11856 -25.31625,-56.4375 -56.4375,-56.4375c-31.12125,0 -56.4375,25.31894 -56.4375,56.4375v7.55725c-4.81062,2.79231 -8.0625,7.98994 -8.0625,13.94275c0,8.89294 7.23206,16.125 16.125,16.125h0.13706c1.40556,25.42106 22.47019,45.6875 48.23794,45.6875c25.76775,0 46.83238,-20.26644 48.23794,-45.6875h0.13706c8.89294,0 16.125,-7.23206 16.125,-16.125c0,-5.95281 -3.25188,-11.15044 -8.0625,-13.94275zM34.9375,77.9375v-5.375h16.125c7.40944,0 13.4375,-6.02806 13.4375,-13.4375v-5.375h-5.375v5.375c0,4.44512 -3.61738,8.0625 -8.0625,8.0625h-15.83744c2.69556,-25.63875 24.43475,-45.6875 50.77494,-45.6875c26.34019,0 48.07938,20.04875 50.77494,45.6875h-42.71244c-4.44512,0 -8.0625,-3.61738 -8.0625,-8.0625v-5.375h-5.375v5.375c0,7.40944 6.02806,13.4375 13.4375,13.4375h43v5.375h-46.91837c-8.213,0 -14.89413,-6.68113 -14.89413,-14.89413v-9.29337h-5.375v8.94937c0,8.40113 -6.837,15.23813 -15.23813,15.23813zM26.875,94.0625c0,-5.92863 4.82138,-10.75 10.75,-10.75v8.0625h-2.6875c-1.4835,0 -2.6875,1.20131 -2.6875,2.6875c0,1.48619 1.204,2.6875 2.6875,2.6875h2.6875v8.0625c-5.92862,0 -10.75,-4.82137 -10.75,-10.75zM86,150.5c-23.70912,0 -43,-19.29087 -43,-43v-24.1875h11.63687c7.61906,0 14.28675,-4.15488 17.85575,-10.31731c3.48031,6.15438 10.08888,10.31731 17.6515,10.31731h38.85587v24.1875c0,23.70913 -19.29087,43 -43,43zM134.375,104.8125v-8.0625h2.6875c1.4835,0 2.6875,-1.20131 2.6875,-2.6875c0,-1.48619 -1.204,-2.6875 -2.6875,-2.6875h-2.6875v-8.0625c5.92863,0 10.75,4.82137 10.75,10.75c0,5.92863 -4.82137,10.75 -10.75,10.75z" fill="url(#color-4_TUOBhQt-Vj1j_gr4)"></path>
</g>
</g>
</svg>
</div>
</div>
<div class="row">
<div class="col">
<div class="fs-12 m-t-5 all-caps">{{ __('Label') }}</div>
</div>
</div>
</div>
</div>
</div>
</div>
@@ -0,0 +1,12 @@
@extends('layouts.base_portal')
@section('inner_content')
<div class="tabsContainer p-3 p-b-0 p-md-0">
<div class="row" v-if="$store.getters.isAdmin">
<div class="col bg-white padding-25">
<div class="row tabsContainer tabContent m-l-0 m-r-0" tab-name="segment1">
<segment-company-component section="customSegmentSection" />
</div>
</div>
</div>
</div>
@endsection
File diff suppressed because one or more lines are too long
-8
View File
@@ -1,11 +1,3 @@
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-T3XCNMB');</script>
<!-- End Google Tag Manager -->
<meta http-equiv="content-type" content="text/html;charset=UTF-8"/>
<meta charset="utf-8"/>
<title>@yield('title', 'IZYIM Shipping')</title>
+22 -3
View File
@@ -802,7 +802,14 @@ Route::get('/invoices/fix/{company_module_id}', function($company_module_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,
@@ -828,8 +835,16 @@ Route::get('/invoices/combine/{ids}', function($ids){
$ids = json_decode($ids);
$transactions = Transaction::whereIn('id', $ids)->get();
$invoice = $transactions[0]; //NOTE: invoices that need to be combined need to be seperated before and after SST implementation
$pdf = LaravelMpdf::loadView('pages.pdfs.shipping_invoices_combined', ['invoice_transactions' => $transactions]);
$view = 'pages.pdfs.shipping_invoices_combined';
$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_invoices_sst_combined';
}
$pdf = LaravelMpdf::loadView($view, ['invoice_transactions' => $transactions]);
return $pdf->download('combined_invoice_.pdf');
})->name('invoice.combined_summary');
@@ -1255,7 +1270,7 @@ Route::get('/payment-and-billing-2', function () {
})->name('admin.payment-and-billing-2');
Route::get('/show-all-extra-payments', function () {
ini_set('memory_limit', '-1');
ini_set('memory_limit', '-1');
$invoices = Transaction::where('type', TransactionType::SHIPPING_INVOICE)
->where('status', ApprovalStatus::COMPLETED)
@@ -1296,3 +1311,7 @@ Route::get('/show-all-extra-payments', function () {
}
echo '</table>';
});
Route::get('/segments', function (Request $request) {
return view('pages.segments.index');
})->name('segments');