Compare commits

...

114 Commits

Author SHA1 Message Date
Cleison Freitas df283e54a2 Company rename endpoint. 2023-01-10 23:03:35 -03:00
Omair Saleh 4c023aa393 export customer total yearly cbm 2023-01-05 10:41:38 +08:00
Omair Saleh 7922c10e2c export customer total yearly cbm 2023-01-05 10:39:04 +08:00
Omair Saleh 742fdf307b export customer total yearly cbm 2023-01-05 10:37:27 +08:00
Omair Saleh df993fe491 export customer total yearly cbm 2023-01-04 12:17:44 +08:00
Omair Saleh 5f5707718f show reference number for package 2023-01-04 11:29:40 +08:00
Omair Saleh d7d9a065fd show reference number for package 2023-01-04 11:23:16 +08:00
EDMOND MING 568d45808a Merge branch 'export-top-order-pdf' into 'master'
export top order pdf

See merge request CIEFWorldwideSdnBhd/shipping-portal!138
2023-01-03 05:47:39 +00:00
edmondlang 715051076c export top order pdf 2023-01-03 00:41:12 +08:00
Omair Saleh 7642f6e9d3 regenerate invoices for specific customers 2022-12-30 17:35:28 +08:00
Omair Saleh 84ad39ac11 regenerate invoices for specific customers 2022-12-30 17:35:07 +08:00
Omair Saleh 03b44cf71d regenerate invoices for specific customers 2022-12-30 17:34:33 +08:00
Omair Saleh 0b577c22f4 regenerate invoices for specific customers 2022-12-30 17:33:29 +08:00
Omair Saleh cabb7b7d63 regenerate invoices for specific customers 2022-12-30 17:32:34 +08:00
Omair Saleh 880d3fc8ce regenerate invoices for specific customers 2022-12-30 17:29:00 +08:00
Omair Saleh 8d901505fe regenerate invoices for specific customers 2022-12-30 17:28:27 +08:00
Omair Saleh 489216e7be regenerate invoices for specific customers 2022-12-30 17:23:56 +08:00
Omair Saleh e413dfa795 regenerate invoices for specific customers 2022-12-30 17:21:47 +08:00
Omair Saleh 4ff5c6df80 update gz warehouse notice 2022-12-26 21:21:00 +08:00
Omair Saleh 762add8e5c fix log data for transactional tables 2022-12-18 15:14:36 +08:00
Omair Saleh 96723461e4 log transactional data 2022-12-16 13:39:19 +08:00
Omair Saleh 2c1431a813 fix over weight minimum charge 2022-12-14 20:16:52 +08:00
Omair Saleh 90ca018e81 fix over weight minimum charge 2022-12-14 20:15:02 +08:00
Omair Saleh 60c51419bb fix over weight minimum charge 2022-12-14 20:07:31 +08:00
Omair Saleh 69f98125a0 fix over weight minimum charge 2022-12-14 20:05:50 +08:00
Omair Saleh f56bfb0309 fix over weight minimum charge 2022-12-14 20:04:02 +08:00
Omair Saleh aedd836211 fix over weight minimum charge 2022-12-14 20:03:11 +08:00
Omair Saleh abfb0ea47b fix over weight minimum charge 2022-12-14 19:57:10 +08:00
Omair Saleh 09461e5bef fix over weight minimum charge 2022-12-14 19:56:21 +08:00
Omair Saleh d5b16f288a fix over weight minimum charge 2022-12-14 19:55:55 +08:00
Omair Saleh 7c1a77089b fix over weight minimum charge 2022-12-14 19:54:19 +08:00
Omair Saleh 505d924eec fix over weight minimum charge 2022-12-14 19:48:39 +08:00
Omair Saleh d0dd802693 fix over weight minimum charge 2022-12-14 19:47:56 +08:00
Omair Saleh 3113cc9fc0 fix over weight minimum charge 2022-12-14 19:47:00 +08:00
Omair Saleh 840e1147c8 fix over weight minimum charge 2022-12-14 19:42:16 +08:00
Omair Saleh 5c89471e14 fix over weight minimum charge 2022-12-14 11:45:28 +08:00
Omair Saleh fbc73e040f fix billplz bill status 2022-12-13 11:03:48 +08:00
Omair Saleh 414f22ab05 fix billplz bill status 2022-12-13 10:56:36 +08:00
Omair Saleh d7328bafdc fix billplz bill status 2022-12-13 10:54:46 +08:00
Omair Saleh 5c5505174a fix billplz bill status 2022-12-13 10:52:51 +08:00
Omair Saleh 6b73d13c33 fix billplz bill status 2022-12-09 12:01:47 +08:00
Omair Saleh 8a62807356 fix billplz bill status 2022-12-09 11:54:16 +08:00
Omair Saleh acca5192b6 estimate container shipping cost 2022-12-07 17:30:48 +08:00
Omair Saleh dfbf22951b estimate container shipping cost 2022-12-02 11:23:40 +08:00
Omair Saleh cc26e67340 estimate container shipping cost 2022-12-02 11:22:47 +08:00
Omair Saleh 15db2715f5 estimate container shipping cost 2022-12-02 11:15:50 +08:00
Omair Saleh 2fc54f796a estimate container shipping cost 2022-12-02 11:01:33 +08:00
Omair Saleh 91b14b3820 estimate container shipping cost 2022-12-02 10:14:37 +08:00
Omair Saleh 7dc549ab2e estimate container shipping cost 2022-12-01 19:08:43 +08:00
Omair Saleh 5480a55edc estimate container shipping cost 2022-12-01 18:44:04 +08:00
Omair Saleh 0cb3bd6ce3 estimate container shipping cost 2022-12-01 18:41:17 +08:00
Omair Saleh f2cc45303c estimate container shipping cost 2022-12-01 18:40:36 +08:00
Omair Saleh e0db537931 estimate container shipping cost 2022-12-01 18:37:50 +08:00
Omair Saleh 53b4af2b5c estimate container shipping cost 2022-12-01 18:35:24 +08:00
Omair Saleh c9d2041653 estimate container shipping cost 2022-12-01 18:31:43 +08:00
Omair Saleh 53e9fcaeb8 debug minimum charge 2022-11-29 15:14:34 +08:00
Omair Saleh 7e007e7d78 debug minimum charge 2022-11-29 15:07:32 +08:00
Omair Saleh 7c879c8633 add bcc to invoice notification email for testing 2022-11-25 11:42:20 +08:00
Omair Saleh 9f255664ac show add/edit billing address to admin 2022-11-24 09:52:12 +08:00
Omair Saleh 63918b4eb0 update china on hold list 2022-11-22 12:10:24 +08:00
Omair Saleh ae36513635 round up cbm to 3 decimals 2022-11-16 16:52:01 +08:00
Omair Saleh 7ac66080ec update export invoice 2022-11-16 16:45:33 +08:00
Omair Saleh 4b699345b8 update export invoice 2022-11-16 16:32:45 +08:00
Omair Saleh 634a97f3b4 minor changes to dummy data seeder comments 2022-11-15 19:56:03 +08:00
Omair Saleh 8a4810d961 remove lockdown announcement from order form 2022-11-15 15:07:33 +08:00
Omair Saleh ab3ba64d31 show anitha debtor ui 2022-11-14 15:01:56 +08:00
Omair Saleh 7bca4be9b9 show anitha debtor ui 2022-11-14 14:54:43 +08:00
Omair Saleh 4f12c7c8ac show anitha debtor ui 2022-11-14 14:53:37 +08:00
Omair Saleh 759a9c19d7 show anitha debtor ui 2022-11-14 14:21:25 +08:00
Omair Saleh 6fa72a4195 show anitha debtor ui 2022-11-14 14:19:06 +08:00
Omair Saleh c82581dcc4 show anitha debtor ui 2022-11-14 14:13:55 +08:00
Omair Saleh d4a63c0095 disable notification for non production enviroments 2022-11-10 21:13:28 +08:00
Omair Saleh 22b03669c6 disable notification for non production enviroments 2022-11-10 21:11:45 +08:00
Omair Saleh 58e9e80fd9 dummy data seed 2022-11-10 20:32:14 +08:00
Omair Saleh 4dab73fc8e re-release yd paid orders 2022-11-09 12:00:25 +08:00
Omair Saleh 9b87f26ca3 re-release yd paid orders 2022-11-09 11:56:43 +08:00
Omair Saleh cd81683816 add container summary for billing report 2022-11-07 13:18:59 +08:00
Omair Saleh 169fac4ab0 add container summary for billing report 2022-11-07 13:17:22 +08:00
Omair Saleh 34b4482139 add container summary for billing report 2022-11-07 13:16:42 +08:00
Omair Saleh 945e8585d4 show edit billing address at invoice pending approval 2022-11-07 10:57:11 +08:00
Omair Saleh 68cb7b7df1 show edit billing address at invoice pending approval 2022-11-07 10:51:32 +08:00
Omair Saleh 84b6750bcc show edit billing address at invoice pending approval 2022-11-07 10:21:27 +08:00
Omair Saleh 7f766cde6a Invoice reminder and shipment update notification emails 2022-11-07 09:38:03 +08:00
Omair Saleh 5d1bb976f8 misc fixes 2022-11-07 08:20:24 +08:00
Omair Saleh 529eb1be93 GZ warehouse close notice 2022-11-03 20:28:30 +08:00
Omair Saleh 95fd0aa45d shipping sales report 2022-11-01 15:45:46 +08:00
Omair Saleh 64a7e4e0b7 shipping sales report 2022-11-01 15:41:28 +08:00
Omair Saleh de4577346c shipping sales report 2022-11-01 15:36:37 +08:00
Omair Saleh 0ac9ca38f2 shipping sales report 2022-11-01 15:34:15 +08:00
Omair Saleh 4b79039a18 shipping sales report 2022-11-01 15:32:39 +08:00
Omair Saleh 4b32a48e07 shipping sales report 2022-11-01 15:30:53 +08:00
Omair Saleh eb09993397 yd api to fetch 30 days 2022-11-01 12:36:29 +08:00
Omair Saleh 627d782e5d yd api to fetch 30 days 2022-11-01 12:35:17 +08:00
Omair Saleh 04771cec4f yd api to fetch 30 days 2022-11-01 12:24:48 +08:00
Omair Saleh d7630af675 fix payment due date days filter 2022-10-31 12:30:24 +08:00
Omair Saleh 37c710def6 fix payment due date days filter 2022-10-30 20:41:20 +08:00
Omair Saleh 7423588324 fix payment due date days filter 2022-10-30 20:38:36 +08:00
Omair Saleh cb76e86c75 fix payment due date days filter 2022-10-30 20:37:43 +08:00
Omair Saleh cb862123b5 fix payment due date days filter 2022-10-30 20:37:02 +08:00
Omair Saleh 032efcb96b fix payment due date days filter 2022-10-30 20:35:54 +08:00
Omair Saleh a90730d616 fix payment due date days filter 2022-10-30 20:35:01 +08:00
Omair Saleh d5026df3a5 fix payment due date days filter 2022-10-30 20:33:33 +08:00
Omair Saleh 6dd3849bff fix payment due date days filter 2022-10-30 20:31:46 +08:00
Omair Saleh 9e4bad1eee fix payment due date days filter 2022-10-30 19:02:29 +08:00
Omair Saleh e356573715 fix payment due date days filter 2022-10-30 19:01:51 +08:00
Omair Saleh de6cb6a75f fix payment due date days filter 2022-10-30 18:59:47 +08:00
Omair Saleh 524da42526 fix payment due date days filter 2022-10-30 18:56:19 +08:00
Omair Saleh 1abc99fe10 fix payment due date days filter 2022-10-30 18:46:14 +08:00
Omair Saleh e91e770bf3 fix payment due date days filter 2022-10-30 18:41:55 +08:00
omair saleh 2e5d39fe96 Merge branch '417-payment-filter' into 'master'
Payment filter

See merge request CIEFWorldwideSdnBhd/shipping-portal!137
2022-10-30 10:28:25 +00:00
omair saleh 6efa78e40d Merge branch 'master' into '417-payment-filter'
# Conflicts:
#   app/Http/Resources/PackingListResource.php
2022-10-30 10:28:19 +00:00
Fairuz df862b7107 Payment filter 2022-10-30 17:44:14 +08:00
Omair Saleh 9df97f3db5 whitelist replica 3992WHE 2022-10-28 12:26:14 +08:00
Omair Saleh aa2ce980bc fix export invoice 2022-10-27 15:57:27 +08:00
51 changed files with 1870 additions and 286 deletions
@@ -95,4 +95,4 @@ abstract class AbstractControllerLogic
return $this->response(json_decode($collection->response()->getContent(), true));
}
}
}
@@ -39,6 +39,11 @@ abstract class AbstractListRecord extends AbstractGetRecord
$query = $query->orderBy($filters->get('order_by')->column, $filters->get('order_by')->DESC ? 'DESC': 'ASC');
}
if($filters->has('group_by')){
$query = $query->groupBy($filters->get('group_by')->column);
}
//dd($query->toSql());
return $filters->has('per_page') ? $query->paginate($filters->get('per_page')) : $query->get();
}
@@ -0,0 +1,37 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\SegmentConstants;
use App\Classes\ValueObjects\Constants\TransactionType;
use Illuminate\Database\Eloquent\Builder;
class CreditTerm implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder;
return $builder->whereHas('packingLists.owner', function($query) use($value) {
$query->whereHas('companyModule.connections', function($query) use($value){
if ($value) {
$query->whereHas('segments', function($query) {
$query->where('segments.id' , 3);
});
}else{
$query->whereDoesntHave('segments', function($query) {
$query->where('segments.id' , 3);
});
}
});
});
}
}
@@ -0,0 +1,29 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\SegmentConstants;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\PackingList;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;
class PackingListOrderedByInvoiceDate implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->select('packing_lists.*')->join('transactions', function($join){
$join->on('transactions.owner_id', '=', 'packing_lists.id');
$join->where('transactions.owner_type', '=', PackingList::class);
$join->where('transactions.status', '=', ApprovalStatus::APPROVED);
})->orderBy('transactions.updated_at', 'DESC');
}
}
@@ -0,0 +1,24 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
class PaymentDay implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->whereHas('transactions', function (Builder $query) use($value) {
$query->where('transactions.type', 1)->where('status', ApprovalStatus::APPROVED)->whereDate('updated_at', '<=', Carbon::now()->subdays($value));
});
}
}
+47
View File
@@ -0,0 +1,47 @@
<?php
namespace App\Classes\General\Traits;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Str;
trait LogData
{
public static function boot()
{
parent::boot();
static::updating(function($model)
{
$tableName = Str::singular($model->table).'_logs';
$relationshipColumn = Str::singular($model->table).'_id';
$originalData = $model->getRawOriginal();
$originalData[$relationshipColumn] = $originalData['id'];
unset($originalData['id']);
if (!Schema::hasTable($tableName)) {
DB::statement('CREATE TABLE '.$tableName.' LIKE '.$model->table);
$indexs = DB::select('SHOW INDEX FROM '.$tableName.';');
$removedIndexes = [];
foreach ($indexs as $index){
if($index->Column_name === 'id' || in_array($index->Key_name, $removedIndexes)) continue;
DB::statement('ALTER TABLE '.$tableName.' drop index '.$index->Key_name);
$removedIndexes[] = $index->Key_name;
}
DB::statement('ALTER TABLE '.$tableName.' ADD COLUMN `'.$relationshipColumn.'` BIGINT NOT NULL AFTER `id`');
}
DB::table($tableName)->insert($originalData);
});
}
}
@@ -67,4 +67,4 @@ class AuthenticationProcessor
}
}
}
@@ -23,4 +23,4 @@ class AuthenticatesUser
}
}
}
@@ -0,0 +1,73 @@
<?php
namespace App\Classes\Modules\Companies\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Companies\Services\UpdatesCompanyModuleName;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\Modules\Companies\Standards\Rules\CanUpdateCompany;
use App\Classes\Modules\Companies\DataTransferObjects\CompanyObject;
use App\Classes\Modules\Companies\Services\UpdatesCompanyName;
use App\Http\Resources\CompanyResource;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class UpdateCompanyNameLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Updated Company',
'message' => 'You have successfully updated the Company'
];
}
/** @var FetchesCompany */
private $fetchesCompany;
/** @var UpdatesCompanyName */
private $updatesCompanyName;
/** @var UpdatesCompanyModuleName */
private $updatesCompanyModuleName;
/**
* UpdateCompanyControllersLogic constructor.
* @param FetchesCompany $fetchesCompany
* @param UpdatesCompanyName $updatesCompany
* @param UpdatesCompanyModuleName $updatesCompanyModuleName
*/
public function __construct(FetchesCompany $fetchesCompany,UpdatesCompanyName $updatesCompanyName, UpdatesCompanyModuleName $updatesCompanyModuleName)
{
$this->fetchesCompany = $fetchesCompany;
$this->updatesCompanyName = $updatesCompanyName;
$this->updatesCompanyModuleName = $updatesCompanyModuleName;
}
/**
* @param Request $request
* @return JsonResponse
* @throws ErrorException
*/
public function logic(Request $request) : JsonResponse
{
$query = $this->fetchesCompany->execute(['id' => $request->route('id')]);
$object = new CompanyObject($request->input('name'), $query->reference, $query->type);
$this->updatesCompanyName->execute($query, $object);
$this->updatesCompanyModuleName->execute($query->companyModules()->first(), $object->getName());
return $this->resourceResponse(new CompanyResource($query));
}
}
@@ -0,0 +1,24 @@
<?php
namespace App\Classes\Modules\Companies\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Classes\Modules\Companies\DataTransferObjects\CompanyObject;
use App\Models\Company;
class UpdatesCompanyName extends AbstractUpdateRecord
{
/**
* @param Company $model
* @param int $status
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(Company $model, CompanyObject $object)
{
$model->name = $object->getName();
return $this->handler($model);
}
}
@@ -0,0 +1,84 @@
<?php
namespace App\Classes\Modules\Exports\Services;
use App\Classes\ValueObjects\Constants\PackingListType;
use App\Models\CompanyModule;
use App\Models\Company;
use App\Models\PackingList;
use Carbon\Carbon;
use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Illuminate\Http\Request;
class ExportsCustomerTotalOrderByYear implements FromCollection, WithHeadings, WithHeadingRow, WithMapping, ShouldAutoSize
{
use Exportable;
private $request;
public function __construct(Request $request)
{
$this->request = $request;
}
public function headings(): array
{
return [
'CompanyId',
'CompanyName',
'CompanyReference',
'TotalCbm'
];
}
/**
* @return \Illuminate\Support\Collection|mixed
*/
public function collection()
{
$packingLists = PackingList::where('type', PackingListType::SHIPPING_PACKING_LIST)->whereHas('containers', function($container){
return $container->where('loading_date', '>=', Carbon::parse('01-01-' . $this->request->route('year')))
->where('loading_date', '<=', Carbon::parse('31-12-' . $this->request->route('year')));
})->get();
$packingLists = $packingLists->groupBy(function ($packingList){
return $packingList->owner->company_module_id;
})->sortByDesc(function($companyModule){
return $companyModule->sum(function($packingList){
return $packingList->packages->sum(function ($package){
return (($package->width / 100) * ($package->height / 100) * ($package->length / 100)) * $package->quantity;
});
});
})->take(10);
return $packingLists;
}
/**
* @param $row
* @return array
*/
public function map($row): array
{
$companyModule = $row[0]->owner->companyModule;
$marking = $companyModule->inviters()->withPivot('invitee_reference')->first()->pivot->invitee_reference;
$cbm = $row->sum(function($packingList){
return $packingList->packages->sum(function ($package){
return (($package->width / 100) * ($package->height / 100) * ($package->length / 100)) * $package->quantity;
});
});
return [
$companyModule->company_id,
$companyModule->name,
$marking,
$cbm
];
}
}
@@ -63,16 +63,21 @@ class ExportsPaymentTransactions implements FromQuery, WithHeadings, WithHeading
$query->where('type', TransactionType::SHIPPING_INVOICE)->whereIn('status', [ApprovalStatus::COMPLETED]);
if($start_date && $end_date) {
$query->whereBetween('created_at', [
$query->whereBetween('updated_at', [
Carbon::parse($start_date)->format('Y-m-d 0:00:00'),
Carbon::parse($end_date)->format('Y-m-d 23:59:59')
]);
}
elseif($start_date && !$end_date) {
$query->where('created_at', '>=', Carbon::parse($start_date)->format('Y-m-d 0:00:00'));
$query->whereHas('transactions', function($transaction) use ($start_date) {
$transaction->where('type', TransactionType::PAYMENT)->where('updated_at', '>=', Carbon::parse($start_date)->format('Y-m-d 0:00:00'));
});
}
elseif(!$start_date && $end_date) {
$query->where('created_at', '<=', Carbon::parse($end_date)->format('Y-m-d 23:59:59'));
$query->whereHas('transactions', function($transaction) use ($end_date) {
$transaction->where('type', TransactionType::PAYMENT)->where('updated_at', '>=', Carbon::parse($end_date)->format('Y-m-d 0:00:00'));
});
}
return $query;
@@ -24,6 +24,8 @@ use App\Classes\Modules\Unity\Processors\AssignContractEntityProcessor;
use App\Classes\Modules\Unity\Processors\CreateContractEntityProcessor;
use App\Classes\Modules\Unity\Services\CreatesContract;
use App\Classes\Modules\Unity\Services\UpdatesContractObligation;
use App\Classes\Notifications\ShipmentDepartureEmail;
use App\Classes\Notifications\ShipmentRescheduleEmail;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\ContainerTypes;
use App\Classes\ValueObjects\Constants\OrderRoleTypes;
@@ -138,7 +140,7 @@ class FetchOrderListsFromYdPortalProcessor
public function execute(?Carbon $start = null, ?Carbon $end = null)
{
try {
$start = $start ? $start : Carbon::today()->subDays(5);
$start = $start ? $start : Carbon::today()->subDays(30);
$startLimit = Carbon::parse('01-12-2021');
@@ -235,17 +237,21 @@ class FetchOrderListsFromYdPortalProcessor
$client = new \GuzzleHttp\Client(['cookies' => true, 'headers' => ['Cookie' => 'utc_offset=480']]);
$request = $client->request('get', 'https://main.universe.com.my/Tracking/User/Paging?sEcho=1&sTrackingNo='.$row->expressno.'&sOrgId=sti');
$deliveryTracking = json_decode($request->getBody()->getContents());
foreach (array_reverse($deliveryTracking->aaData) as $trackingRow) {
$trackingDate = Carbon::createFromFormat('d/m/y H:i', $trackingRow->LocalDateTime);
if (Str::contains($trackingRow->PublicDescription, ['accepted/picked'])){
$unstuffingDate = $trackingDate;
}
try {
$request = $client->request('get', 'https://main.universe.com.my/Tracking/User/Paging?sEcho=1&sTrackingNo='.$row->expressno.'&sOrgId=sti');
$deliveryTracking = json_decode($request->getBody()->getContents());
foreach (array_reverse($deliveryTracking->aaData) as $trackingRow) {
$trackingDate = Carbon::createFromFormat('d/m/y H:i', $trackingRow->LocalDateTime);
if (Str::contains($trackingRow->PublicDescription, ['accepted/picked'])){
$unstuffingDate = $trackingDate;
}
if (Str::contains($trackingRow->PublicDescription, ['delivered'])) {
$deliveryDate = $trackingDate;
if (Str::contains($trackingRow->PublicDescription, ['delivered'])) {
$deliveryDate = $trackingDate;
}
}
} catch (\Exception $exception){
Log::debug('failed to fetch delivery tracking');
}
$customerno = preg_split('(-|\(|\)|\/)', $row->customerno);
@@ -352,7 +358,7 @@ class FetchOrderListsFromYdPortalProcessor
if($order instanceof Order){
$marking = $order->companyModule->inviters()->withPivot('invitee_reference')->first()->pivot->invitee_reference;
if(!in_array($marking, ['2192KAA', '2353GFE', '6866DTR', '153DSR', '1291NSC', '8288MIB', '1152AAT', '962LOW', '3992WHE', '1290CSW', '9493TYS', '3397GSH'])){
if(!in_array($marking, ['1290CSW', '8997ITB', '3992WHE', '962LOW', '1152AAT'])){
$this->fetchesDataFRomYDPortal->clientRequest('http://www.yd-wl.com/api/confirmsendorder.ashx', 'GET', [
'expressno' => $row->expressno
]);
@@ -401,6 +407,13 @@ class FetchOrderListsFromYdPortalProcessor
$etd = $transport->schedules()->where('status', '=', ApprovalStatus::APPROVED)->first()->etd;
$transport->schedules()->update(['status' => ApprovalStatus::EXPIRED]);
$this->createsSchedule->execute($transport, new ScheduleObject($etd, $delayDate, ApprovalStatus::APPROVED));
foreach ($container->packingLists as $packingList){
if(!($packingList->owner instanceof Order)) continue;
$user = $packingList->owner->companyModule->employees()->first();
if(app()->environment(['production'])) {
$user->notify(new ShipmentRescheduleEmail($user, $packingList));
}
}
}
}
@@ -3,6 +3,7 @@
namespace App\Classes\Modules\Transactions\ControllersLogic;
use App\Classes\Notifications\InvoiceIssuedEmail;
use Illuminate\Http\Request;
@@ -87,8 +88,11 @@ class ApproveShippingInvoiceTransactionLogic extends AbstractControllerLogic
$document = $this->createsDocument->execute($invoice_transaction, $document_object);
$this->createsFiles->execute($document, $document_object);
$user = $packing_list->owner->companyModule->employees()->first();
if(app()->environment(['production'])) {
$user->notify(new InvoiceIssuedEmail($user, $packing_list));
}
return $this->response([]);
}
}
}
@@ -25,6 +25,7 @@ use App\Classes\ValueObjects\Constants\PackageType;
use App\Classes\ValueObjects\Constants\SegmentConstants;
use App\Classes\ValueObjects\Constants\TransactionDetailType;
use App\Models\CompanyModule;
use App\Models\Document;
use App\Models\PackingList;
use App\Models\Transaction;
@@ -69,11 +70,11 @@ class CreateShippingInvoiceTransactionLogic extends AbstractControllerLogic
/** @var CreatesFiles */
private $createsFile;
public function __construct(
FetchesPackingList $fetchesPackingList,
FetchesSegmentConstant $fetchesSegmentConstant,
GeneratesTransactionBillNumber $generatesTransactionBillNumber,
FetchesPackingList $fetchesPackingList,
FetchesSegmentConstant $fetchesSegmentConstant,
GeneratesTransactionBillNumber $generatesTransactionBillNumber,
CreatesTransaction $createsTransaction,
CreatesTransactionDetail $createsTransactionDetail,
CreatesDocument $createsDocument,
@@ -99,13 +100,13 @@ class CreateShippingInvoiceTransactionLogic extends AbstractControllerLogic
$billable_packing_list = $billable_packing_list ? $billable_packing_list : $packing_list;
$cbm = $billable_packing_list->packages->where('type', '!=', PackageType::OVER_WEIGHT)->sum(function($package) {
$cbm = round($billable_packing_list->packages->where('type', '!=', PackageType::OVER_WEIGHT)->sum(function($package) {
return ($package->width / 100) * ($package->height / 100) *($package->length / 100) * ($package->quantity);
});
}), 3);
$over_weight_cbm = $billable_packing_list->packages->where('type', PackageType::OVER_WEIGHT)->sum(function($package) {
$over_weight_cbm = round($billable_packing_list->packages->where('type', PackageType::OVER_WEIGHT)->sum(function($package) {
return ($package->width / 100) * ($package->height / 100) *($package->length / 100) * ($package->quantity);
});
}), 3);
$order = $packing_list->owner;
$companyModule = $order->companyModule;
@@ -120,11 +121,7 @@ class CreateShippingInvoiceTransactionLogic extends AbstractControllerLogic
$noMinimumCharge = $connection->segments()->where('segments.id', 2)->first();
$base_price = 0;
$warehouse_rate = 0;
$state_rate = 0;
$minimum_cbm = 0.3;
$segment_price = 0;
$state_select = '';
$segment_price = $connection->segments()->whereHas('constants', function($query){
@@ -156,6 +153,7 @@ class CreateShippingInvoiceTransactionLogic extends AbstractControllerLogic
$hasMinimumCharge = null;
foreach ($container->packingLists as $packingList){
if($packingList->owner instanceof CompanyModule) continue;
if($packingList->owner->companyModule->id !== $companyModule->id) continue;
$containerPackingLists->push($packingList);
@@ -170,15 +168,17 @@ class CreateShippingInvoiceTransactionLogic extends AbstractControllerLogic
$totalContainerCbm = $containerPackingLists->sum(function($packingList){
$billable_packing_list = $packingList->packingLists()->first();
$billable_packing_list = $billable_packing_list ? $billable_packing_list : $packingList;
return $billable_packing_list->packages->where('type', '!=', PackageType::OVER_WEIGHT)->sum(function($package) {
return $billable_packing_list->packages->sum(function($package) {
return ($package->width / 100) * ($package->height / 100) *($package->length / 100) * ($package->quantity);
});
});
$minimum_charge = $minimum_cbm - $totalContainerCbm;
$minimum_charge = $minimum_charge < 0 ? 0 : $minimum_charge;
$minimum_charge = ($minimum_charge < 0) ? 0 : $minimum_charge;
$minimum_charge = $noMinimumCharge ? 0 : $minimum_charge;
$minimum_charge = $noMinimumCharge ? 0 : round($minimum_charge, 3);
if($hasMinimumCharge) {
$minimum_charge = 0;
@@ -191,20 +191,20 @@ class CreateShippingInvoiceTransactionLogic extends AbstractControllerLogic
$billNumber = $this->generatesTransactionBillNumber->execute('SHIP-');
$object = new TransactionObject(
$billNumber,
TransactionType::SHIPPING_INVOICE,
1,
$billNumber,
TransactionType::SHIPPING_INVOICE,
1,
$order->company_module_id,
1,
1,
PaymentMethodType::CASH,
$total_cbm,
$total_cbm,
1,
1,
0,
0,
1,
0,
null,
0,
0,
null,
ApprovalStatus::PENDING_SUBMISSION
);
+5 -2
View File
@@ -2,14 +2,17 @@
namespace App\Classes\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;
class AbstractEmail extends Notification
class AbstractEmail extends Notification implements ShouldQueue
{
use Queueable;
public function via()
{
return 'mail';
}
}
}
@@ -0,0 +1,49 @@
<?php
namespace App\Classes\Notifications;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\PackingList;
use App\Models\PasswordReset;
use App\Models\User;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Support\Facades\Storage;
class InvoiceIssuedEmail extends AbstractEmail
{
/** @var User */
private $user;
/** @var PackingList */
private $packingList;
/**
* @param User $user
* @param PackingList $packingList
*/
public function __construct(User $user, PackingList $packingList)
{
$this->user = $user;
$this->packingList = $packingList;
}
public function toMail()
{
$invoice = $this->packingList->transactions()->where('type', TransactionType::SHIPPING_INVOICE)->where('status', ApprovalStatus::APPROVED)->first();
$invoiceDocument = $invoice->documents()->first()->files;
return (new MailMessage)
->subject('Att: '.$this->user->name.' - Invoice for order no.'. $this->packingList->owner->reference)
->attach(Storage::disk('documents')->get($invoiceDocument->file->file_info->original->file), [
'as' => 'name.pdf',
'mime' => 'application/pdf',
])->view('emails.shipment.invoice', ['user' => $this->user, 'packingList' => $this->packingList]);
}
}
@@ -0,0 +1,52 @@
<?php
namespace App\Classes\Notifications;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\PackingList;
use App\Models\PasswordReset;
use App\Models\User;
use Illuminate\Notifications\Messages\MailMessage;
class ShipmentDepartureEmail extends AbstractEmail
{
/** @var User */
private $user;
/** @var PackingList */
private $packingList;
/**
* @param User $user
* @param PackingList $packingList
*/
public function __construct(User $user, PackingList $packingList)
{
$this->user = $user;
$this->packingList = $packingList;
}
public function toMail()
{
$invoice = $this->packingList->transactions()->where('type', TransactionType::SHIPPING_INVOICE)->where('status', ApprovalStatus::APPROVED)->first();
if(!$invoice) return false;
$invoiceDocument = $invoice->documents()->first()->files;
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->file->file_info->original->file), [
'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,39 @@
<?php
namespace App\Classes\Notifications;
use App\Models\PackingList;
use App\Models\PasswordReset;
use App\Models\User;
use Illuminate\Notifications\Messages\MailMessage;
class ShipmentRescheduleEmail extends AbstractEmail
{
/** @var User */
private $user;
/** @var PackingList */
private $packingList;
/**
* @param User $user
* @param PackingList $packingList
*/
public function __construct(User $user, PackingList $packingList)
{
$this->user = $user;
$this->packingList = $packingList;
}
public function toMail()
{
return (new MailMessage)
->subject('Update on your recent shipment(s)')
->bcc(['email_test@cief-malaysia.com'])->view('emails.shipment.reschedule', ['user' => $this->user, 'packingList' => $this->packingList]);
}
}
@@ -32,7 +32,7 @@ class UserVerificationEmail extends AbstractEmail
{
return (new MailMessage)
->subject('Email Verification')
->view('emails.accounts.user_verification', ['user' => $this->user, 'attempt' => $this->attempt]);
->bcc(['email_test@cief-malaysia.com'])->view('emails.accounts.user_verification', ['user' => $this->user, 'attempt' => $this->attempt]);
}
@@ -47,7 +47,7 @@ final class WarehouseReferences {
public const MIN_CBM_EXEMPT_LIST = [230, 294, 320, 652, 1248, 1726, 2349, 2574];
public const REPLICA_WHITE_LIST = [502];
public const REPLICA_WHITE_LIST = [502, 2237];
//2376 qce
@@ -0,0 +1,64 @@
<?php
namespace App\Console\Commands;
use App\Classes\Notifications\InvoiceIssuedEmail;
use App\Classes\Notifications\ShipmentDepartureEmail;
use App\Http\Helpers\General;
use App\Models\Order;
use Carbon\Carbon;
use App\Models\Container;
use Illuminate\Console\Command;
class SendContainerDepartureEmailCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'command:sendContainerDepartureEmailCommand';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$containers = Container::whereHas('transports', function ($transport){
return $transport->whereDate('dispatch_date', '=', Carbon::today());
})->get();
foreach ($containers as $container){
foreach ($container->packingLists as $packingList){
if(!($packingList->owner instanceof Order)) continue;
$user = $packingList->owner->companyModule->employees()->first();
if(app()->environment(['production'])) {
$user->notify(new ShipmentDepartureEmail($user, $packingList));
}
}
}
}
}
+5
View File
@@ -38,6 +38,11 @@ class Kernel extends ConsoleKernel
->withoutOverlapping()
->appendOutputTo (storage_path().'/logs/curlyd.log');
$schedule->command('command:curlYdOrderListCommand')
->cron('0 9 * * *')
->withoutOverlapping()
->appendOutputTo (storage_path().'/logs/departure_email.log');
}
@@ -0,0 +1,21 @@
<?php
namespace App\Http\Controllers\Companies;
use App\Classes\Modules\Companies\ControllersLogic\UpdateCompanyNameLogic;
use App\Http\Controllers\Controller;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class UpdateCompanyNameController extends Controller
{
/**
* @param Request $request
* @param UpdateCompanyLogic $logic
* @return JsonResponse
*/
public function rename(Request $request, UpdateCompanyNameLogic $logic): JsonResponse
{
return $logic->execute($request);
}
}
@@ -4,6 +4,7 @@ namespace App\Http\Controllers\Exports;
use App\Classes\Modules\Exports\Services\ExportsCustomersOrderLatestDate;
use App\Classes\Modules\Exports\Services\ExportsCustomerTotalOrderByYear;
use App\Classes\Modules\Exports\Services\ExportsPaymentTransactions;
use App\Models\User;
use Illuminate\Http\Request;
@@ -31,4 +32,11 @@ class ExportCustomersToExcelController
ob_end_clean();
return $response;
}
public function totalOrders(Request $request){
$exportsTotalOrders = new ExportsCustomerTotalOrderByYear($request);
$response = $exportsTotalOrders->download('total-orders-' . $request->route('year') . '.xls', Excel::XLS, ['Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']);
ob_end_clean();
return $response;
}
}
+1
View File
@@ -29,6 +29,7 @@ class PackageResource extends JsonResource
'weight' => $this->weight,
'quantity' => $this->quantity,
'cbm' => (($this->width / 100) * ($this->height / 100) * ($this->length / 100)) * $this->quantity,
'reference' => $this->packingList->reference,
'status' => $this->status,
$this->mergeWhen($originalPackingList->owner instanceof Order, [
'order' => New OrderResource($originalPackingList->owner)
+2
View File
@@ -4,6 +4,7 @@ namespace App\Models;
use App\Classes\General\Interfaces\Remarkable;
use App\Classes\General\Interfaces\Transportable;
use App\Classes\General\Traits\LogData;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\MorphMany;
@@ -14,6 +15,7 @@ class Container extends AbstractModel implements Transportable, Remarkable
{
use HasRelationships;
use SoftDeletes;
use LogData;
protected $table = 'containers';
+2
View File
@@ -7,6 +7,7 @@ use App\Classes\General\Interfaces\Transportable;
use App\Classes\General\Interfaces\Packable;
use App\Classes\General\Interfaces\Transactionable;
use App\Classes\General\Traits\LogData;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
@@ -23,6 +24,7 @@ class PackingList extends AbstractModel implements Transportable, Steppable, Pac
use HasTableAlias;
use HasRelationships;
use SoftDeletes;
use LogData;
protected $table = 'packing_lists';
+2
View File
@@ -5,6 +5,7 @@ namespace App\Models;
use App\Classes\General\Interfaces\Documentable;
use App\Classes\General\Interfaces\Remarkable;
use App\Classes\General\Interfaces\Transactionable;
use App\Classes\General\Traits\LogData;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use Carbon\Carbon;
@@ -18,6 +19,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
class Transaction extends AbstractModel implements Documentable, Transactionable, Remarkable
{
use SoftDeletes;
use LogData;
protected $table = 'transactions';
+2 -1
View File
@@ -3,6 +3,7 @@
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Schema;
class AppServiceProvider extends ServiceProvider
{
@@ -23,6 +24,6 @@ class AppServiceProvider extends ServiceProvider
*/
public function boot()
{
//
Schema::defaultStringLength(191);
}
}
+1 -1
View File
@@ -106,7 +106,7 @@ return [
|
*/
'faker_locale' => 'en_US',
'faker_locale' => 'ms_MY',
/*
|--------------------------------------------------------------------------
+1 -1
View File
@@ -57,7 +57,7 @@ return [
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'engine' => 'InnoDB ROW_FORMAT=DYNAMIC',
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
+2 -11
View File
@@ -13,22 +13,13 @@ class DatabaseSeeder extends Seeder
*/
public function run()
{
$this->call(AdminUsersTableSeeder::class);
$this->call(CountriesTableSeeder::class);
$this->call(StatesTableSeeder::class);
$this->call(DistrictsTableSeeder::class);
$this->call(CountriesTableSeeder::class);
$this->call(CurrenciesTableSeeder::class);
$this->call(CompaniesTableSeeder::class);
$this->call(SegmentsTableSeeder::class);
$this->call(SegmentConstantsTableSeeder::class);
// $this->call(OrdersTableSeeder::class);
$this->call(DummyDataSeeder::class);
}
}
}
+588
View File
@@ -0,0 +1,588 @@
<?php
namespace Database\Seeders;
use App\Classes\Exceptions\AccessForbiddenException;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\RequestValidationException;
use App\Classes\General\Services\GeneratesInitials;
use App\Classes\Modules\Accounts\DataTransferObjects\RegistrationObject;
use App\Classes\Modules\Accounts\Services\CreatesUser;
use App\Classes\Modules\Addresses\DataTransferObjects\AddressObject;
use App\Classes\Modules\Addresses\Services\CreatesAddress;
use App\Classes\Modules\Companies\DataTransferObjects\CompanyConnectionObject;
use App\Classes\Modules\Companies\DataTransferObjects\CompanyModuleObject;
use App\Classes\Modules\Companies\DataTransferObjects\CompanyObject;
use App\Classes\Modules\Companies\DataTransferObjects\EmploymentObject;
use App\Classes\Modules\Companies\Processors\AssignEmployeeProcessor;
use App\Classes\Modules\Companies\Services\ApprovesCompanyConnection;
use App\Classes\Modules\Companies\Services\CreatesCompany;
use App\Classes\Modules\Companies\Services\CreatesCompanyConnection;
use App\Classes\Modules\Companies\Services\CreatesCompanyModule;
use App\Classes\Modules\Companies\Services\GeneratesUniqueAccountNumber;
use App\Classes\Modules\Contacts\DataTransferObjects\ContactObject;
use App\Classes\Modules\Contacts\Services\CreatesContact;
use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject;
use App\Classes\Modules\Documents\Services\CreatesDocument;
use App\Classes\Modules\Documents\Services\CreatesFiles;
use App\Classes\Modules\Orders\Processors\CreateOrderProcessor;
use App\Classes\Modules\Orders\Services\GeneratesOrderNumber;
use App\Classes\Modules\PackingLists\DataTransferObjects\ContainerObject;
use App\Classes\Modules\PackingLists\DataTransferObjects\PackageObject;
use App\Classes\Modules\PackingLists\DataTransferObjects\PackingListObject;
use App\Classes\Modules\PackingLists\Processors\CreateContainerProcessor;
use App\Classes\Modules\PackingLists\Processors\CreatePackageProcessor;
use App\Classes\Modules\PackingLists\Processors\CreatePackingListProcessor;
use App\Classes\Modules\Schedules\DataTransferObjects\ScheduleObject;
use App\Classes\Modules\Schedules\Services\CreatesSchedule;
use App\Classes\Modules\Transports\DataTransferObjects\TransportObject;
use App\Classes\Modules\Transports\Services\CreatesTransport;
use App\Classes\ValueObjects\Constants\AddressType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\BusinessType;
use App\Classes\ValueObjects\Constants\CompanyType;
use App\Classes\ValueObjects\Constants\ContainerTypes;
use App\Classes\ValueObjects\Constants\DocumentType;
use App\Classes\ValueObjects\Constants\PackageType;
use App\Classes\ValueObjects\Constants\PackingListType;
use App\Classes\ValueObjects\Constants\RoleTypes;
use App\Classes\ValueObjects\Constants\TransportType;
use App\Models\Address;
use App\Models\Company;
use App\Models\CompanyModule;
use App\Models\Container;
use App\Models\Document;
use App\Models\PackingList;
use App\Models\Transport;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Database\Seeder;
use Faker\Generator as Faker;
class DummyDataSeeder extends Seeder
{
/** @var Faker */
public $faker;
/** @var CreatesUser */
public $createsUser;
/** @var GeneratesUniqueAccountNumber */
public $generatesUniqueAccountNumber;
/** @var CreatesCompany */
public $createsCompany;
/** @var CreatesCompanyModule */
public $createsCompanyModule;
/** @var CreatesContact */
public $createsContact;
/** @var CreatesAddress */
public $createsAddress;
/** @var CreateContainerProcessor */
public $createContainerProcessor;
/** @var CreatesTransport */
public $createsTransport;
/** @var CreatesSchedule */
public $createsSchedule;
/** @var CreatesCompanyConnection */
public $createsCompanyConnection;
/** @var ApprovesCompanyConnection */
public $approvesCompanyConnection;
/** @var AssignEmployeeProcessor */
public $assignEmployeeProcessor;
/** @var CreatesDocument */
public $createsDocument;
/** @var CreatesFiles */
public $createsFiles;
/** @var GeneratesOrderNumber */
public $generatesOrderNumber;
/** @var CreateOrderProcessor */
public $createOrderProcessor;
/** @var CreatePackingListProcessor */
public $createPackingListProcessor;
/** @var CreatePackageProcessor */
public $createPackageProcessor;
/**
* @param Faker $faker
* @param CreatesUser $createsUser
* @param GeneratesUniqueAccountNumber $generatesUniqueAccountNumber
* @param CreatesCompany $createsCompany
* @param CreatesCompanyModule $createsCompanyModule
* @param CreatesContact $createsContact
* @param CreatesAddress $createsAddress
* @param CreateContainerProcessor $createContainerProcessor
* @param CreatesTransport $createsTransport
* @param CreatesSchedule $createsSchedule
* @param CreatesCompanyConnection $createsCompanyConnection
* @param ApprovesCompanyConnection $approvesCompanyConnection
* @param AssignEmployeeProcessor $assignEmployeeProcessor
* @param CreatesDocument $createsDocument
* @param CreatesFiles $createsFiles
* @param GeneratesOrderNumber $generatesOrderNumber
* @param CreateOrderProcessor $createOrderProcessor
* @param CreatePackingListProcessor $createPackingListProcessor
* @param CreatePackageProcessor $createPackageProcessor
*/
public function __construct(Faker $faker, CreatesUser $createsUser, GeneratesUniqueAccountNumber $generatesUniqueAccountNumber, CreatesCompany $createsCompany, CreatesCompanyModule $createsCompanyModule, CreatesContact $createsContact, CreatesAddress $createsAddress, CreateContainerProcessor $createContainerProcessor, CreatesTransport $createsTransport, CreatesSchedule $createsSchedule, CreatesCompanyConnection $createsCompanyConnection, ApprovesCompanyConnection $approvesCompanyConnection, AssignEmployeeProcessor $assignEmployeeProcessor, CreatesDocument $createsDocument, CreatesFiles $createsFiles, GeneratesOrderNumber $generatesOrderNumber, CreateOrderProcessor $createOrderProcessor, CreatePackingListProcessor $createPackingListProcessor, CreatePackageProcessor $createPackageProcessor)
{
$this->faker = $faker;
$this->createsUser = $createsUser;
$this->generatesUniqueAccountNumber = $generatesUniqueAccountNumber;
$this->createsCompany = $createsCompany;
$this->createsCompanyModule = $createsCompanyModule;
$this->createsContact = $createsContact;
$this->createsAddress = $createsAddress;
$this->createContainerProcessor = $createContainerProcessor;
$this->createsTransport = $createsTransport;
$this->createsSchedule = $createsSchedule;
$this->createsCompanyConnection = $createsCompanyConnection;
$this->approvesCompanyConnection = $approvesCompanyConnection;
$this->assignEmployeeProcessor = $assignEmployeeProcessor;
$this->createsDocument = $createsDocument;
$this->createsFiles = $createsFiles;
$this->generatesOrderNumber = $generatesOrderNumber;
$this->createOrderProcessor = $createOrderProcessor;
$this->createPackingListProcessor = $createPackingListProcessor;
$this->createPackageProcessor = $createPackageProcessor;
}
/**
* Run the database seeds.
*
* @return void
* @throws MalformedRequestException
* @throws AccessForbiddenException
* @throws RequestValidationException
*/
public function run()
{
// Local Development Default Password Hash
$password = '123456abcabc';
// At the moment we only have 3 different user roles:
// RoleTypes::SUPER_ADMIN : Full access, at the moment is not attached to a company but should be in the future.
// RoleTypes::ADMIN : Full access except for some sensitive features that require higher level of approval, at the moment is not attached to a company but should be in the future.
// RoleTypes::USER : This is the customer, can only access their own orders only, must be attached to a company.
// User Status
// ApprovalStatus::PENDING_VERIFICATION : This should be the default status before the user verifies their email status, but currently this is not being implemented.
// ApprovalStatus::APPROVED : This is the status of users with verified emails.
// ApprovalStatus::SUSPENDED : This is the status if the users is blocked from the system, but currently this is not being implemented.
// =============================================== //
// Create CIEF Entities //
// =============================================== //
// create super admin
$userObject = new RegistrationObject($this->faker->name, 'super_admin@izyim.com', $password, $password,RoleTypes::SUPER_ADMIN, ApprovalStatus::APPROVED);
$this->createsUser->execute($userObject);
// create admin
$userObject = new RegistrationObject($this->faker->name, 'admin@izyim.com', $password, $password,RoleTypes::ADMIN, ApprovalStatus::APPROVED);
$this->createsUser->execute($userObject);
// create CIEF
$company_object = new CompanyObject('CIEF Worldwide Sdn Bhd', 'CIEF',CompanyType::COMPANY_BUSINESS,ApprovalStatus::APPROVED);
/** @var Company $company */
$company = $this->createsCompany->execute($company_object);
$companyModuleObject = new CompanyModuleObject('CIEF Worldwide Sdn Bhd', 'CIEF', '', '', BusinessType::FREIGHT_FORWARDER, ApprovalStatus::APPROVED);
/** @var CompanyModule $CIEF */
$CIEF = $this->createsCompanyModule->execute($company, $companyModuleObject);
// =============================================== //
// Create Supplier Entities //
// =============================================== //
// supplier entities consist of 2 type of company module [BusinessType::FREIGHT_FORWARDER, BusinessType::FREIGHT_FORWARDER, BusinessType::WAREHOUSE]
// in this use case we are creating 3 supplier, with each supplier having 6 company modules, 1 BusinessType::FREIGHT_FORWARDER and 5 BusinessType::WAREHOUSE. 1 warehouse for each location.
for ($i = 1; $i <= 3; $i++) {
$supplierName = $this->faker->company;
$supplierReference = $this->faker->bothify('??-????');
$company_object = new CompanyObject($supplierName, $supplierReference,CompanyType::COMPANY_BUSINESS,ApprovalStatus::APPROVED);
/** @var Company $company */
$company = $this->createsCompany->execute($company_object);
$companyModuleObject = new CompanyModuleObject($supplierName, $supplierReference, '', '', BusinessType::FREIGHT_FORWARDER, ApprovalStatus::APPROVED);
$this->createsCompanyModule->execute($company, $companyModuleObject);
// create supplier warehouses
foreach(['Guangzhou', 'Yiwu', 'Klang', 'Sabah', 'Sarawak'] as $name){
$warehouseReference = '';
$isChina = false;
switch($name) {
case 'Guangzhou': $warehouseReference = 'GZ-V0'.$i; $isChina = true; break;
case 'Yiwu': $warehouseReference = 'YY-V0'.$i; $isChina = true; break;
case 'Klang': $warehouseReference = 'KL-V0'.$i; break;
case 'Sabah': $warehouseReference = 'SB-V0'.$i; break;
case 'Sarawak':$warehouseReference = 'SRW-V0'.$i; break;
}
$companyModuleObject = new CompanyModuleObject($name, $warehouseReference, '', '', BusinessType::WAREHOUSE, ApprovalStatus::APPROVED);
/** @var CompanyModule $companyModule */
$companyModule = $this->createsCompanyModule->execute($company, $companyModuleObject);
$address = new AddressObject( $this->faker->streetAddress, $this->faker->streetAddress, $isChina ? 2 : 1, $isChina ? 35 : 15, $isChina ? 633 : 412, $isChina ? 510450 : 41400, AddressType::DELIVERY, ApprovalStatus::APPROVED);
$this->createsAddress->execute($companyModule, $address);
$contact = new ContactObject($this->faker->name, $this->faker->phoneNumber, '', '');
$this->createsContact->execute($companyModule, $contact);
}
}
// =============================================== //
// Create Containers //
// =============================================== //
// Containers belongs to a warehouse, a container will include many packing lists that will be shipped together
// when a container is loaded it will be attached to transport arrangement and a schedule to indicate when the container will depart (ETD) and when it will arrive (ETA)
// the shipping schedule can be interrupted which will result in a delay for the (ETA)
for($containerLoop=1; $containerLoop <= rand(15, 60); $containerLoop++) {
$loadingDate = Carbon::today()->addDays(10)->subDays(rand(1, 30));
$containerObject = new ContainerObject($this->faker->bothify('??-######'), '', '', ContainerTypes::FORTY_FEET_DRY_CONTAINER, $loadingDate, ApprovalStatus::PENDING_VERIFICATION);
// randomly selects an origin warehouse
$warehouse = CompanyModule::where('reference', $this->faker->randomElement(['GZ-V01', 'GZ-V02', 'GZ-V03', 'YY-V01', 'YY-V03', 'YY-V03']))->first();
/** @var Container $container */
$container = $this->createContainerProcessor->execute($containerObject, $warehouse);
$departureDate = $loadingDate->copy()->addDays(rand(0, 3));
$arrivalDate = $departureDate->copy()->addDays(7);
// Container Shipping Schedule
$transportObject = new TransportObject(TransportType::SEA, null, null, $departureDate, null, ApprovalStatus::APPROVED);
/** @var Transport $transport */
$transport = $this->createsTransport->execute($transportObject, $container);
$this->createsSchedule->execute($transport, new ScheduleObject($departureDate, $arrivalDate, ApprovalStatus::APPROVED));
// randomly reschedule some containers
if($this->faker->numberBetween(0, 1)){
$delayedArrivalDate = $departureDate->copy()->addDay();
// reschedule shipment
for($scheduleLoop=1; $scheduleLoop <= rand(1, 5); $scheduleLoop++) {
$delayedArrivalDate = $delayedArrivalDate->copy()->addDays(rand(0, 5));
$transport->schedules()->update(['status' => ApprovalStatus::EXPIRED]);
$this->createsSchedule->execute($transport, new ScheduleObject($departureDate, $delayedArrivalDate, ApprovalStatus::APPROVED));
}
}
}
// =============================================== //
// Create Customer //
// =============================================== //
// 1. create user
// 2. create company
// 3. create Company Module
// 4. Declare Company Relationship with CIEF
// 5. Attach Employee
// 6. create contact
// 7. create Address
// 8. identification verification
// =============================================== //
// Order Workflow //
// =============================================== //
// 9. Create Shipping Label
// 10. Receive Goods at warehouse (our record match supplier record + detect any problems)
// 11. Load into container for shipping (our record match supplier record + detect any problems)
// 12. generate invoice (add billing address + double check price)
// 13. additional charges
// 12. Un-stuffing Container (our record match supplier record + detect any problems)
// 13. last mile delivery (our record match supplier record + on hold)
// generate random number of users
for($userLoop=1; $userLoop <= rand(20, 50); $userLoop++) {
// === //
// 1 // ========== //
// Create user //
// ================= //
$customerName = $this->faker->name;
$customerEmail = $this->faker->email;
$userObject = new RegistrationObject($customerName, $customerEmail, $password, $password, RoleTypes::USER, ApprovalStatus::APPROVED);
/** @var User $user */
$user = $this->createsUser->execute($userObject);
// === //
// 2 // ========== //
// Create Company //
// ================= //
// CompanyTypes
// CompanyType::COMPANY_BUSINESS : For SME Business Entities and requires SSM for identity verification.
// CompanyType::PERSONAL_BUSINESS : For Personal Entities and requires IC for identity verification, and the company name will follow the customer name in this case.
// Company Status
// ApprovalStatus::APPROVED : This is the default status of registered company.
// ApprovalStatus::SUSPENDED : This is the status if the company is blocked from releasing packages from warehouse due to pending verification.
$isCompany = $this->faker->numberBetween(0, 1);
$companyName = $isCompany ? $this->faker->company : $customerName;
$companyAccountNumber = $this->generatesUniqueAccountNumber->execute();
$company_object = new CompanyObject($companyName,
$companyAccountNumber,
$isCompany ? CompanyType::COMPANY_BUSINESS : CompanyType::PERSONAL_BUSINESS,
ApprovalStatus::APPROVED);
/** @var Company $company */
$company = $this->createsCompany->execute($company_object);
// === //
// 3 // =================//
// Create Company Module //
// ========================//
// Company Module are sub entities of the company, and is used to declare what kind of business role this sub entity is in "Like Departments"
// one company can have multiple company module if they play multiple roles in the process:
// BusinessType::IMPORTER :
// BusinessType::FREIGHT_FORWARDER :
// BusinessType::WAREHOUSE :
$companyModuleObject = new CompanyModuleObject($companyName, $companyAccountNumber, '', '', BusinessType::IMPORTER, ApprovalStatus::APPROVED);
/** @var CompanyModule $companyModule */
$companyModule = $this->createsCompanyModule->execute($company, $companyModuleObject);
// === //
// 4 // ================================== //
// Declare Company Relationship with CIEF //
// ========================================= //
// In order for 2 entities to work together they must both agree to the relationship "Like facebook friend requests".
// But at the moment since CIEF is the only Entity that has a direct relationship with importers we just declare this relationship by default.
$connectionObject = new CompanyConnectionObject($companyModule, $CIEF, mt_rand(1000, 9999) . (new GeneratesInitials())->name($companyName)->length(3)->generate(), 'CIEF');
$connection = $this->createsCompanyConnection->execute($connectionObject);
$this->approvesCompanyConnection->execute($connection);
// === //
// 5 // ===========//
// Attach Employee //
// ==================//
// employees are attached to company modules not companies, because an employee maybe working for one or many "Departments".
$Object = new EmploymentObject($companyModule, $user);
$this->assignEmployeeProcessor->execute($Object);
// === //
// 6 // =========== //
// Create Contact //
// ================= //
// Contacts uses eloquent polymorphic relationship to declare its owner. and for this use case it will be attached to the company not the company module.
$contactObject = new ContactObject($customerName, $this->faker->phoneNumber, $customerEmail, null);
$this->createsContact->execute($company, $contactObject);
// === //
// 7 // ========== //
// Create Address //
// ================= //
// Addresses uses eloquent polymorphic relationship to declare its owner. and for this use case it will be attached to the company module.
// an address has at least 1 contact for the PIC.
// there are 2 type of address we use:
// AddressType::DELIVERY : for the orders delivery address
// AddressType::BILLING : for the invoice billing address
foreach ([AddressType::DELIVERY, AddressType::BILLING] as $type) {
// create delivery address
$addressObject = new AddressObject($this->faker->streetAddress, '', 1, $this->faker->numberBetween(1, 15), $this->faker->numberBetween(1, 442), $this->faker->postcode, $type, ApprovalStatus::APPROVED);
/** @var Address $address */
$address = $this->createsAddress->execute($companyModule, $addressObject);
// create delivery address contact for person in charge
$contact = new ContactObject($this->faker->name, $this->faker->phoneNumber, '', '');
$this->createsContact->execute($address, $contact);
}
// === //
// 8 // ======================= //
// identification verification //
// ============================== //
// please refer to company types section for more insight
$object = new DocumentObject($isCompany ? DocumentType::SSM_REGISTRATION : DocumentType::IDENTITY_CARD, ['data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAIAAAB7GkOtAAANGklEQVR4nOzXDa/fdX3G8R44Ww54BIFV2wFyoxUoKmsFhA0zEGQj1jOMo5o5IQPmYE5wrSvjdhbHAGWt0BWEwmChuHEjSF2LrY6tlmFjJbblprQstD21UFzbrBhX1tKyR3ElJtfr9QCu78k/v5N3PoOzbv/SmKR/mv94dP+FN9dH95+7+J7o/sjse6P7y3d/Orq/6qKTovtLN94f3Z9w39nR/XeFv/+nrlse3V/xhbXR/Xuv/kx0f3TDjuj+oltviO7PHJf9/veJrgPwK0sAAEoJAEApAQAoJQAApQQAoJQAAJQSAIBSAgBQSgAASgkAQCkBACglAAClBACglAAAlBIAgFICAFBKAABKCQBAKQEAKCUAAKUEAKCUAACUEgCAUgIAUEoAAEoJAEApAQAoJQAApQQAoJQAAJQafOeyu6MPPP9by6L7f7n/yuj+rWN/Et3/xiu/Gd3/xQduju7ve+KE6P7wc6dG9yde/lx0f86J2e/nO38yLrq/ftXT0f0/m7wzuj9jw4vR/V2n74jub7v8zOi+CwCglAAAlBIAgFICAFBKAABKCQBAKQEAKCUAAKUEAKCUAACUEgCAUgIAUEoAAEoJAEApAQAoJQAApQQAoJQAAJQSAIBSAgBQSgAASgkAQCkBACglAAClBACglAAAlBIAgFICAFBKAABKCQBAKQEAKDWw40dD0Qc2PP+O6P6cJauj+zP+dVl0//izT47uv+eazdH9bf+3I7r/xhFXR/dnzjwmun/lJ56N7n/vA/Oi+5NmnxDdf3jqtuj+8j0PRPfnzPtUdP/Jt++K7rsAAEoJAEApAQAoJQAApQQAoJQAAJQSAIBSAgBQSgAASgkAQCkBACglAAClBACglAAAlBIAgFICAFBKAABKCQBAKQEAKCUAAKUEAKCUAACUEgCAUgIAUEoAAEoJAEApAQAoJQAApQQAoJQAAJQSAIBSgwsfXhl94KuHrIjuHzvmxuj+g6+9EN1//Pz/jO5P/2x2f/dTL0X3f+e9S6L7f3zJHdH9jafOjO6/7/LDo/s3bL4+un/rnNOi+yMXDUX3Bw6YFt2/+IyTovsuAIBSAgBQSgAASgkAQCkBACglAAClBACglAAAlBIAgFICAFBKAABKCQBAKQEAKCUAAKUEAKCUAACUEgCAUgIAUEoAAEoJAEApAQAoJQAApQQAoJQAAJQSAIBSAgBQSgAASgkAQCkBACglAAClBACg1OCEe34UfWDn+SPR/bcWrY3u//DMbdH94w4diu4/sPTo6P7tNx0Z3V92wrzo/k8/uzu6f8DwndH9v5i1ILq/+UO3Rfd3Lz4nuv+VRx6K7s9Y+nJ0f+HKsdF9FwBAKQEAKCUAAKUEAKCUAACUEgCAUgIAUEoAAEoJAEApAQAoJQAApQQAoJQAAJQSAIBSAgBQSgAASgkAQCkBACglAAClBACglAAAlBIAgFICAFBKAABKCQBAKQEAKCUAAKUEAKCUAACUEgCAUgIAUGrw9+84JfrAof89P7r/wf8aG90/d8//RvdvXf/30f3JI8ui+8ceeUd0/+DPr4nuf3jX56L7p168Krr/rcfOiu6PHvhqdH/xLauj+8+Mbozur/vpj6P7E8edH913AQCUEgCAUgIAUEoAAEoJAEApAQAoJQAApQQAoJQAAJQSAIBSAgBQSgAASgkAQCkBACglAAClBACglAAAlBIAgFICAFBKAABKCQBAKQEAKCUAAKUEAKCUAACUEgCAUgIAUEoAAEoJAEApAQAoJQAApQYXb9kafeDSf/lWdP/fdx4c3X9k60vR/b13Xxjdnzb1Z9H90ctWRfffmvRGdP+8e96M7m+avT26/45vnh3d/9rNY6P7Tz/5w+j+e6bMj+4f8rHro/vHH579/l0AAKUEAKCUAACUEgCAUgIAUEoAAEoJAEApAQAoJQAApQQAoJQAAJQSAIBSAgBQSgAASgkAQCkBACglAAClBACglAAAlBIAgFICAFBKAABKCQBAKQEAKCUAAKUEAKCUAACUEgCAUgIAUEoAAEoJAECpwb037R994NK5a6P7/7zgvuj+JTNPiO7/7fKjo/t7H7wmuj/8+pnR/f2nbojuH33tndH9333536L7E25+Kro//NuTo/vLT1oe3f+jNZdG9y+ffHB0f972e6L7LgCAUgIAUEoAAEoJAEApAQAoJQAApQQAoJQAAJQSAIBSAgBQSgAASgkAQCkBACglAAClBACglAAAlBIAgFICAFBKAABKCQBAKQEAKCUAAKUEAKCUAACUEgCAUgIAUEoAAEoJAEApAQAoJQAApQQAoNTgYcd8LvrA9IGd0f3jh6+K7l8/d010f5/hrdH98euGovuf+OvbovsHnPpSdP/p6X8e3d8ztD26v+bJydH9GQfcG91/+MWPRve/vPSX0f2P/OmC6P7AdYdF910AAKUEAKCUAACUEgCAUgIAUEoAAEoJAEApAQAoJQAApQQAoJQAAJQSAIBSAgBQSgAASgkAQCkBACglAAClBACglAAAlBIAgFICAFBKAABKCQBAKQEAKCUAAKUEAKCUAACUEgCAUgIAUEoAAEoJAECpgXMG3x59YPXKWdH9xc9+P7q/3/SjovvLjjs3uv83E4+N7p904Lej+9MXfCq6//ULvxvdf2D2KdH9afOuiu5PnPm26P7QM1Oy+yPZ7/PItdui+1v+Y1103wUAUEoAAEoJAEApAQAoJQAApQQAoJQAAJQSAIBSAgBQSgAASgkAQCkBACglAAClBACglAAAlBIAgFICAFBKAABKCQBAKQEAKCUAAKUEAKCUAACUEgCAUgIAUEoAAEoJAEApAQAoJQAApQQAoJQAAJQaeOKXH48+sGnNtOj+mGkrovNvm3tddH/MoWOj8y/cckx0/6D5743u/+ydI9H9O/d+JLr/yuwLovtbHhqI7r//wuz3+Z2PfTC6/5VXVkX3/+G+c6L7Xz9vRnTfBQBQSgAASgkAQCkBACglAAClBACglAAAlBIAgFICAFBKAABKCQBAKQEAKCUAAKUEAKCUAACUEgCAUgIAUEoAAEoJAEApAQAoJQAApQQAoJQAAJQSAIBSAgBQSgAASgkAQCkBACglAAClBACglAAAlBp4/ZC7og/84cLx0f1fX7gyuj/xy6PR/eueuDG6P/6rS6L7t//g8ej+Xa9Niu6/9sSM6P4bmx6L7t+14+Do/se/NBzd3/7Rq6L7a976dHR/xruy/1+jO/aN7rsAAEoJAEApAQAoJQAApQQAoJQAAJQSAIBSAgBQSgAASgkAQCkBACglAAClBACglAAAlBIAgFICAFBKAABKCQBAKQEAKCUAAKUEAKCUAACUEgCAUgIAUEoAAEoJAEApAQAoJQAApQQAoJQAAJQSAIBSg48/PyX6wBenDkX3Z607Lbo/d9f7o/tblmd//5u+Oyu6f/rP50X3B1/dEN2/5O6V0f0rLr0tur/omp9E918deT26/+Dpe6P7N179d9H9TdeORvd33XdOdN8FAFBKAABKCQBAKQEAKCUAAKUEAKCUAACUEgCAUgIAUEoAAEoJAEApAQAoJQAApQQAoJQAAJQSAIBSAgBQSgAASgkAQCkBACglAAClBACglAAAlBIAgFICAFBKAABKCQBAKQEAKCUAAKUEAKCUAACUGpgzcW/0gQ9PPyK6P/jtB6P7nzxrU3T/i/dvjO6vPuWQ6P6Z7/616P76T94Q3X/37qHo/rzfmx/dv2V8dv/+/S6L7j/6B0uj+wftuyS6v+KK7O+/++Xs3+8CACglAAClBACglAAAlBIAgFICAFBKAABKCQBAKQEAKCUAAKUEAKCUAACUEgCAUgIAUEoAAEoJAEApAQAoJQAApQQAoJQAAJQSAIBSAgBQSgAASgkAQCkBACglAAClBACglAAAlBIAgFICAFBKAABKDTx24TeiDzz68MnR/UU7D4/uH/ah7P6PH5oT3T/viCuj+18b2RTd//7J+0f3L7nipuj+lAueie6PmXpUdH7mpDOi+y/ueiS6f9kP/iq6/+yEn0f3p1x0UXTfBQBQSgAASgkAQCkBACglAAClBACglAAAlBIAgFICAFBKAABKCQBAKQEAKCUAAKUEAKCUAACUEgCAUgIAUEoAAEoJAEApAQAoJQAApQQAoJQAAJQSAIBSAgBQSgAASgkAQCkBACglAAClBACglAAAlBo86urN0Qemjk6N7n9v+Nzo/uHXfj66P3fF1uj+Pvv9T3T/wBOj82MeOuvR6P64cVdE9/9x4KDo/m+cdmV0f8HSPdH9910wKbo//gv3Rve/+YszovufufO46L4LAKCUAACUEgCAUgIAUEoAAEoJAEApAQAoJQAApQQAoJQAAJQSAIBSAgBQSgAASgkAQCkBACglAAClBACglAAAlBIAgFICAFBKAABKCQBAKQEAKCUAAKUEAKCUAACUEgCAUgIAUEoAAEoJAEApAQAo9f8BAAD//3aYjHM9JD/iAAAAAElFTkSuQmCC'],
$isCompany ? $this->faker->bothify('SSM-#######') : $this->faker->bothify('############'), ApprovalStatus::APPROVED, 'identifications');
/** @var Document $document */
$document = $this->createsDocument->execute($company, $object);
$this->createsFiles->execute($document, $object);
// generate random number of shipping labels
for($orderLoop=1; $orderLoop <= rand(1, 30); $orderLoop++) {
// === //
// 9 // ================= //
// Create Shipping Label //
// ======================== //
// The shipping label is stored in the warehouse as an order entity.
// the shipping label comes with the warehouse address which will receive the shipment, and
// the shipping label comes with a qr code that helps the supplier warehouse to identify
// the customer that owns the order and the delivery address.
// A shipping label can be re-used, and each batch that arrives at the supplier warehouse
// is referred to as a packing list. more on this later.
$orderNumber = $this->generatesOrderNumber->execute();
$deliveryAddress = $company->addresses()->where('type', AddressType::DELIVERY);
// randomly selects an origin warehouse
$originWarehouse = CompanyModule::where('reference', $this->faker->randomElement(['GZ-V01', 'GZ-V02', 'GZ-V03', 'YY-V01', 'YY-V03', 'YY-V03']))->first();
// creates shipping label
$order = $this->createOrderProcessor->execute($company, $originWarehouse, $address, $orderNumber);
// Packing List Types
// A packing list is a group of packages, there are many type of packing lists, but currently we are only using 4 types of packing list:
// PackingListType::WAREHOUSE_RECEIVE_LIST : group of packages that has arrived to the warehouse with the original measurements provided by the warehouse.
// PackingListType::WAREHOUSE_RECEIVE_LIST_REPLICA : group of packages that has arrived to the warehouse with the modified measurements. e.g. add 1 cm to width, length, and height.
// PackingListType::SHIPPING_PACKING_LIST : group of packages that has packed into the container with the original measurements provided by the warehouse.
// PackingListType::SHIPPING_PACKING_LIST_REPLICA : group of packages that has packed into the container with the modified measurements. e.g. add 1 cm to width, length, and height.
if($orderLoop !== 1) {
// generate random number of packing lists
for($packingListLoop=1; $packingListLoop <= rand(2, 4); $packingListLoop++) {
// ==== //
// 10 // ===================== //
// Receive Goods at warehouse //
// WAREHOUSE_RECEIVE_LIST //
// ============================= //
// When a batch of goods arrives to the warehouse a WAREHOUSE_RECEIVE_LIST packing list is created.
// A transport arrangement is attached to WAREHOUSE_RECEIVE_LIST packing list to represent the trip
// from supplier to the warehouse and is used to record the arrival date.
// create random packages
$packages = [];
for ($packagesLoop = 1; $packagesLoop <= rand(2, 5); $packagesLoop++) {
$packages[] = new PackageObject(PackageType::CARTON, $this->faker->word, (float)$this->faker->numberBetween(1, 100), (float)$this->faker->numberBetween(1, 100), (float)$this->faker->numberBetween(1, 100), 0, (float)$this->faker->numberBetween(1, 10), ApprovalStatus::APPROVED);
}
$packingListReference = $this->faker->bothify('???#########');
$warehouseReceiveObject = new PackingListObject($packingListReference, $originWarehouse->id, PackingListType::WAREHOUSE_RECEIVE_LIST, ApprovalStatus::APPROVED);
// Creates WAREHOUSE_RECEIVE_LIST & WAREHOUSE_RECEIVE_LIST_REPLICA
/** @var PackingList $warehouseReceiveList */
$warehouseReceiveList = $this->createPackingListProcessor->execute($warehouseReceiveObject, $order);
// attach packages to packing list
foreach ($packages as $package) {
// Attach packages to both WAREHOUSE_RECEIVE_LIST & WAREHOUSE_RECEIVE_LIST_REPLICA
$this->createPackageProcessor->execute($package, $warehouseReceiveList);
}
// random arrival date in the last 30 days
$receiveDate = Carbon::today()->subDays(rand(10, 45));
// create transport arrangement for the trip from manufacturer to warehouse (to record drop off/ receive date)
$transportObject = new TransportObject(TransportType::LAND, null, $this->faker->bothify('??#########'), $receiveDate, $receiveDate, ApprovalStatus::APPROVED);
$this->createsTransport->execute($transportObject, $warehouseReceiveList);
// ==== //
// 11 // =========================== //
// Load into container for shipping //
// SHIPPING_PACKING_LIST //
// =================================== //
// When a batch of goods is loaded in a container to prepare for shipping a SHIPPING_PACKING_LIST packing list is created.
// A SHIPPING_PACKING_LIST is a copy of the WAREHOUSE_RECEIVE_LIST in most cases.
$shippingPackingListObject = new PackingListObject($packingListReference, $originWarehouse->id, PackingListType::SHIPPING_PACKING_LIST, ApprovalStatus::APPROVED);
// Creates SHIPPING_PACKING_LIST & SHIPPING_PACKING_LIST_REPLICA
/** @var PackingList $warehouseReceiveList */
$shippingPackingList = $this->createPackingListProcessor->execute($shippingPackingListObject, $order);
// attach packages to packing list
foreach ($packages as $package) {
// Attach packages to both SHIPPING_PACKING_LIST & SHIPPING_PACKING_LIST_REPLICA
$this->createPackageProcessor->execute($package, $shippingPackingList);
}
// select random container
$container = $this->faker->randomElement(Container::whereDate('loading_date', '>=', $receiveDate)->get());
// attach packing list to container
$container->packingLists()->attach($shippingPackingList);
if ($container->status !== ApprovalStatus::COMPLETED) {
// ==== //
// 12 // ================================= //
// Un-stuffing Container //
// container arrived to malaysia warehouse //
// ========================================= //
// when a container arrives to malaysia's warehouse it is un-stuffed, the un-stuffing date will update
// the container's transport drop off date and to container status is update to ApprovalStatus::COMPLETE
$containerTransport = $container->transports()->first();
$schedule = $containerTransport->schedules()->where('status', ApprovalStatus::APPROVED)->first();
// container Has arrived
if ($schedule->eta->isPast()) {
// update transport drop date
$containerTransport->drop_date = $schedule->eta;
$containerTransport->save();
// update container status to complete
$container->status = ApprovalStatus::COMPLETED;
$container->save();
// ==== //
// 13 // ================ //
// Last Mile Delivery //
// ======================== //
// after the container is un-stuffed, the malaysian warehouse will arrange for delivery.
// to schedule the delivery we will need to attach a transport arrangement with a schedule to the SHIPPING_PACKING_LIST
$isDelivered = rand(0, 1);
if ($isDelivered) {
$deliveryDate = $schedule->eta->copy()->addDays(rand(1, 5));
$transportObject = new TransportObject(TransportType::LAND, null, null, $deliveryDate, $deliveryDate, ApprovalStatus::APPROVED);
/** @var Transport $transport */
$transport = $this->createsTransport->execute($transportObject, $shippingPackingList);
$this->createsSchedule->execute($transport, new ScheduleObject($deliveryDate, $deliveryDate, ApprovalStatus::APPROVED));
}
}
}
}
}
}
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //
// Missing Functions //
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //
// 1. on hold shipments
// 2. invoices & payments
// 3. overweight cbm
}
}
}
@@ -4,6 +4,7 @@ namespace Database\Seeders;
use App\Classes\ValueObjects\Constants\SegmentConstants;
use App\Classes\ValueObjects\Constants\WarehouseReferences;
use App\Models\SegmentConstant;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
@@ -23,105 +24,91 @@ class SegmentConstantsTableSeeder extends Seeder
public function run()
{
// insert base prices
$n_days = 10; // for the 10 days ahead
$today = date("Y-m-d");
$prices = [];
for($ii=0; $ii<$n_days;$ii++){
$prices[date('Y-m-d', strtotime($today. ' + '.$ii.' days'))] = rand(10, 30) / 10;
}
$this->insertData(1, SegmentConstants::BASE_PRICE, $prices);
Segmentconstant::create( [
'segment_id'=>1,
'reference'=>'BASE_PRICE',
'value'=>'{"2022-09-21":"330.00","2022-09-22":"330.00","2022-09-23":"330.00","2022-09-24":"330.00","2022-09-25":"330.00","2022-09-26":"330.00","2022-09-27":"315.00","2022-09-28":"315.00","2022-09-29":"315.00","2022-09-30":"315.00","2022-08-22":"330.00","2022-08-23":"330.00","2022-08-24":"330.00","2022-08-25":"330.00","2022-08-26":"330.00","2022-08-27":"330.00","2022-08-28":"330.00","2022-08-29":"330.00","2022-08-30":"330.00","2022-08-31":"330.00","2022-09-01":"330.00","2022-09-02":"330.00","2022-09-03":"330.00","2022-09-04":"330.00","2022-09-05":"330.00","2022-09-06":"330.00","2022-09-07":"330.00","2022-09-08":"330.00","2022-09-09":"330.00","2022-09-10":"330.00","2022-09-11":"330.00","2022-09-12":"330.00","2022-09-13":"330.00","2022-09-14":"330.00","2022-09-15":"330.00","2022-09-16":"330.00","2022-09-17":"330.00","2022-09-18":"330.00","2022-09-19":"330.00","2022-09-20":"330.00","2022-10-01":"315.00","2022-10-02":"315.00","2022-10-03":"315.00","2022-10-04":"315.00","2022-10-05":"315.00","2022-10-06":"315.00","2022-10-07":"315.00","2022-10-08":"315.00","2022-10-09":"315.00","2022-10-10":"315.00","2022-10-11":"315.00","2022-10-12":"315.00","2022-10-13":"315.00","2022-10-14":"315.00","2022-10-15":"315.00","2022-10-16":"315.00","2022-10-17":"315.00","2022-10-18":"315.00","2022-10-19":"315.00","2022-10-20":"315.00","2022-10-21":"315.00","2022-10-22":"315.00","2022-10-23":"315.00","2022-10-24":"315.00","2022-10-25":"315.00","2022-10-26":"315.00","2022-10-27":"315.00","2022-10-28":"315.00","2022-10-29":"315.00","2022-10-30":"315.00","2022-10-31":"315.00","2022-11-01":"315.00","2022-11-02":"315.00","2022-11-03":"315.00","2022-11-04":"315.00","2022-11-05":"315.00","2022-11-06":"315.00","2022-11-07":"315.00","2022-11-08":"315.00","2022-11-09":"315.00","2022-11-10":"315.00","2022-11-11":"315.00","2022-11-12":"315.00","2022-11-13":"315.00","2022-11-14":"315.00","2022-11-15":"315.00","2022-11-16":"315.00","2022-11-17":"315.00","2022-11-18":"315.00","2022-11-19":"315.00","2022-11-20":"315.00","2022-11-21":"315.00","2022-11-22":"315.00","2022-11-23":"315.00","2022-11-24":"315.00","2022-11-25":"315.00","2022-11-26":"315.00","2022-11-27":"315.00","2022-11-28":"315.00","2022-11-29":"315.00","2022-11-30":"315.00","2022-12-01":"315.00","2022-12-02":"315.00","2022-12-03":"315.00","2022-12-04":"315.00","2022-12-05":"315.00","2022-12-06":"315.00","2022-12-07":"315.00","2022-12-08":"315.00","2022-12-09":"315.00","2022-12-10":"315.00","2022-12-11":"315.00","2022-12-12":"315.00","2022-12-13":"315.00","2022-12-14":"315.00","2022-12-15":"315.00","2022-12-16":"315.00","2022-12-17":"315.00","2022-12-18":"315.00","2022-12-19":"315.00","2022-12-20":"315.00","2022-12-21":"315.00","2022-12-22":"315.00","2022-12-23":"315.00","2022-12-24":"315.00","2022-12-25":"315.00","2022-12-26":"315.00","2022-12-27":"315.00","2022-12-28":"315.00","2022-12-29":"315.00","2022-12-30":"315.00","2022-12-31":"315.00"}',
'deleted_at'=>NULL,
'created_at'=>NULL,
'updated_at'=>'2022-09-27 01:16:14'
] );
// insert state prices
$prices = [];
for($ii=1; $ii<=16;$ii++){
$prices[] = [
'state_id' => $ii,
'center' => '10.00',
'outstation'=> '2.00'
];
}
$this->insertData(1, SegmentConstants::STATE_RATE, $prices);
// insert warehouse prices
$prices = [];
for($ii=1; $ii<=7;$ii++){
$prices[] = [
'warehouse_id' => $ii,
'amount' => '1.'.$ii
];
}
$this->insertData(1, SegmentConstants::WAREHOUSE_RATE, $prices);
// insert center postcodes
$prices = [
[ 'post_code' => '80050' ],
[ 'post_code' => '80100' ],
[ 'post_code' => '80150' ],
[ 'post_code' => '80200' ],
[ 'post_code' => '80250' ],
[ 'post_code' => '80300' ],
[ 'post_code' => '80350' ],
[ 'post_code' => '80400' ],
[ 'post_code' => '80500' ],
[ 'post_code' => '80506' ],
[ 'post_code' => '80508' ],
[ 'post_code' => '80516' ],
[ 'post_code' => '80519' ],
[ 'post_code' => '80534' ],
[ 'post_code' => '80536' ],
[ 'post_code' => '80542' ],
[ 'post_code' => '80546' ],
[ 'post_code' => '80558' ],
[ 'post_code' => '80560' ],
[ 'post_code' => '80564' ],
[ 'post_code' => '80568' ],
[ 'post_code' => '80578' ],
[ 'post_code' => '80584' ],
[ 'post_code' => '80586' ],
[ 'post_code' => '80590' ],
[ 'post_code' => '80592' ],
[ 'post_code' => '80594' ],
[ 'post_code' => '80596' ],
[ 'post_code' => '80600' ],
[ 'post_code' => '80604' ],
[ 'post_code' => '80608' ],
[ 'post_code' => '80620' ],
[ 'post_code' => '80622' ],
[ 'post_code' => '80628' ],
[ 'post_code' => '80644' ],
[ 'post_code' => '80648' ],
[ 'post_code' => '80662' ],
[ 'post_code' => '80664' ],
[ 'post_code' => '80668' ],
[ 'post_code' => '80670' ],
[ 'post_code' => '80672' ],
[ 'post_code' => '80673' ],
[ 'post_code' => '80676' ],
[ 'post_code' => '80700' ],
[ 'post_code' => '80710' ],
[ 'post_code' => '80720' ],
[ 'post_code' => '80730' ],
[ 'post_code' => '80900' ],
[ 'post_code' => '80902' ],
[ 'post_code' => '80904' ],
[ 'post_code' => '80906' ],
[ 'post_code' => '80908' ],
[ 'post_code' => '80988' ],
[ 'post_code' => '80990' ],
[ 'post_code' => '81000' ],
[ 'post_code' => '81100' ],
[ 'post_code' => '81200' ],
[ 'post_code' => '81300' ],
[ 'post_code' => '81310' ]
];
$this->insertData(1, SegmentConstants::CENTER_POSTCODE, $prices);
Segmentconstant::create( [
'segment_id'=>1,
'reference'=>'STATE_RATE',
'value'=>'[{"state_id":1,"center":"10.00","outstation":"2.00"},{"center":"10.00","outstation":"0.00"},{"center":"10.00","outstation":"0.00"},{"center":"50.00","outstation":"0.00"},{"center":"0.00","outstation":"0.00"},{"center":"345.00","outstation":"0.00"},{"center":"10.00","outstation":"0.00"},{"center":"10.00","outstation":"0.00"},{"center":"10.00","outstation":"0.00"},{"center":"10.00","outstation":"0.00"},{"center":"10.00","outstation":"0.00"},{"center":"10.00","outstation":"0.00"},{"center":"0.00","outstation":"0.00"},{"center":"185.00","outstation":"0.00"},{"center":"185.00","outstation":"0.00"},{"center":"0.00","outstation":"0.00"},{"center":"50.00","outstation":"0.00"}]',
'deleted_at'=>NULL,
'created_at'=>NULL,
'updated_at'=>'2022-09-27 01:18:15'
] );
// insert outstation prices
$prices = [
['post_code' => '80000' ]
];
$this->insertData(1, SegmentConstants::OUTSTATION_POSTCODE, $prices);
Segmentconstant::create( [
'segment_id'=>1,
'reference'=>'WAREHOUSE_RATE',
'value'=>'{"4":{"amount":"20.00"},"2358":{"amount":"20.00"}}',
'deleted_at'=>NULL,
'created_at'=>NULL,
'updated_at'=>'2022-09-23 04:22:52'
] );
Segmentconstant::create( [
'segment_id'=>1,
'reference'=>'CENTER_POSTCODE',
'value'=>'["5150","5460","8000","9600","10150","10350","11600","12200","12200","12200","14000","14300","18000","27600","28500","28700","31150","31350","31400","31450","36000","40150","40150","40160","40300","40400","40460","41050","41200","42000","42000","42100","42200","43000","43100","43200","43200","43300","43500","43500","43700","43900","46050","46100","46200","46300","47000","47100","47120","47130","47170","47301","47400","47500","47630","47800","48050","50450","51200","52000","52100","52200","54200","55000","55100","56000","56100","57000","58000","60000","62050","63000","68100","70300","70450","71800","75250","75260","76100","76100","79150","81000","81100","81200","81300","81750","83000","86000","88300","88300","88300","88450","91000","98000","98100"]',
'deleted_at'=>NULL,
'created_at'=>NULL,
'updated_at'=>'2022-11-07 03:01:11'
] );
Segmentconstant::create( [
'segment_id'=>1,
'reference'=>'OUTSTATION_POSTCODE',
'value'=>'["93250","93350","94200","94300","94600","78556","78557","94700","94750","94760","93050","93250","94000","94500","93050","93350","93350","79466","93050","94100","94500","93050","93050","93250","93350","93050","94200","94200","93010","93010","94700","94800","94807","94809","93250","94000","93050","93050","93250","86900","82300","86800","86810","81600","86800","71600","71650","72400","71600","72200","72300","71750","71770","69000","26800","26810","26820","39000","39007","39009","39010","33300","33310","33320","33100"]',
'deleted_at'=>NULL,
'created_at'=>NULL,
'updated_at'=>'2022-09-21 03:35:19'
] );
Segmentconstant::create( [
'segment_id'=>4,
'reference'=>'CUSTOM_PRICE',
'value'=>'["-10.00"]',
'deleted_at'=>NULL,
'created_at'=>'2022-09-21 02:23:22',
'updated_at'=>'2022-09-21 03:50:38'
] );
Segmentconstant::create( [
'segment_id'=>5,
'reference'=>'CUSTOM_PRICE',
'value'=>'["-20.00"]',
'deleted_at'=>NULL,
'created_at'=>'2022-09-21 03:51:23',
'updated_at'=>'2022-09-21 03:51:59'
] );
Segmentconstant::create( [
'segment_id'=>6,
'reference'=>'CUSTOM_PRICE',
'value'=>'["-30.00"]',
'deleted_at'=>NULL,
'created_at'=>'2022-09-21 03:51:46',
'updated_at'=>'2022-09-21 03:52:05'
] );
}
}
+48 -19
View File
@@ -2,6 +2,7 @@
namespace Database\Seeders;
use App\Models\Segment;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
@@ -9,24 +10,52 @@ class SegmentsTableSeeder extends Seeder
{
public function run()
{
DB::table('segments')->insert(
[
[
'id' => 1,
'company_module_id' => 1,
'name' => 'Default Segment',
],
[
'id' => 2,
'company_module_id' => 1,
'name' => 'No Minimum Charge',
],
[
'id' => 3,
'company_module_id' => 1,
'name' => 'Auto Release',
]
]
);
Segment::create( [
'company_module_id'=>1,
'name'=>'Default Segment',
'deleted_at'=>NULL,
'created_at'=>NULL,
'updated_at'=>NULL
] );
Segment::create( [
'company_module_id'=>1,
'name'=>'No Minimum Charge',
'deleted_at'=>NULL,
'created_at'=>NULL,
'updated_at'=>NULL
] );
Segment::create( [
'company_module_id'=>1,
'name'=>'Auto Release',
'deleted_at'=>NULL,
'created_at'=>NULL,
'updated_at'=>NULL
] );
Segment::create( [
'company_module_id'=>1,
'name'=>'Gold Member',
'deleted_at'=>NULL,
'created_at'=>'2022-09-21 02:22:58',
'updated_at'=>'2022-09-21 02:22:58'
] );
Segment::create( [
'company_module_id'=>1,
'name'=>'Platinium Member',
'deleted_at'=>NULL,
'created_at'=>'2022-09-21 03:51:09',
'updated_at'=>'2022-09-21 03:51:09'
] );
Segment::create( [
'company_module_id'=>1,
'name'=>'Titanium Member',
'deleted_at'=>NULL,
'created_at'=>'2022-09-21 03:51:34',
'updated_at'=>'2022-09-21 03:51:34'
] );
}
}
@@ -19,7 +19,7 @@
{{item.order.address.street_one+' '+(item.order.address.street_two ? item.order.address.street_two : '')+', '+ item.order.address.district.name+', '+item.order.address.post_code+' '+item.order.address.state.name+', '+item.order.address.country.name}}<br>{{item.order.address.remark ? item.order.address.remark.content: ''}}
<div class="btn btn-xs btn-primary pointer m-t-10 requestModal hide" data-type="defineLocation">Define Location</div>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="defineLocation">
<declare-postcode-area-form-component :data="item.order.address.post_code"></declare-postcode-area-form-component>
<declare-postcode-area-form-component :data="item.order.address"></declare-postcode-area-form-component>
</modal-component>
</div>
</div>
@@ -19,6 +19,12 @@
<p class="bold m-b-5 fs-12">{{item.description}}</p>
</div>
</div>
<div class="row m-b-10 align-items-center" v-if="$store.getters.isAdmin">
<div class="col-auto">
<p class="no-margin all-caps fs-10 lh-10 light">Reference</p>
<p class="no-margin fs-12">{{item.reference}}</p>
</div>
</div>
<div class="row b-t b-b b-grey m-b-15">
<div class="col">
<div class="row">
@@ -174,4 +180,4 @@
},
mixins: [componentHandler]
}
</script>
</script>
@@ -67,6 +67,14 @@
<p class="no-margin bold text-info fs-12"><a :href="route('customer.profile', item.order.company_module.marking)">{{item.order.company_module.marking}}</a></p>
</div>
</div>
<div class="row m-b-5" v-if="$store.getters.isAdmin">
<div class="col-auto p-r-5">
<p class="no-margin all-caps fs-10 light">Reference</p>
</div>
<div class="col p-l-5">
<p class="no-margin bold text-info fs-12">{{item.reference}}</p>
</div>
</div>
<div class="row m-b-5">
<div class="col-auto p-r-5">
<p class="no-margin all-caps fs-10 light">Order Number</p>
@@ -45,6 +45,7 @@
<div class="col-6">
<div class="row m-t-20">
<div class="col">
<!-- <p class="m-b-0 text-danger m-b-15" v-if="parameters.warehouse_id === 3">As the Baiyun district is still under the control management, our warehouse will be temporarily closed until further notice.</p>-->
<p class="text-center">最新运费价格 <a href="https://www.cief-malaysia.com/services-sea-shipping/" class="text-underline" target="_blank">点击 这里 </a><br>For the latest shipping prices <a href="https://www.cief-malaysia.com/services-sea-shipping/" class="text-underline" target="_blank">click here</a></p>
</div>
</div>
@@ -52,7 +53,7 @@
</div>
<div class="row text-center justify-content-center">
<div class="col-8">
<p class="m-b-0 text-danger m-t-15" v-if="parameters.warehouse_id === 3">近期由于船期的安排和马来西亚海关的运作等一些不可控因数导致船期延迟请大家提前做好采购安排若有不便之处敬请谅解 <br>Due to inevitable circumstances, shipping arrangements and Malaysia custom clearance may have delays. Kindly plan your purchases in advance, thank you for your cooperation.</p>
<p class="m-b-0 text-danger m-t-15" v-if="parameters.warehouse_id === 3">疫情因管控松动飙升其中几位仓库人员也不幸感染整个操作可能会受到影响我们会尽快跟进并恢复<br>The pandemic spread due to the loosening of movement controls. Some warehouse employees were unfortunately infected and the entire operation may be disrupted. We will do our best to follow up and revert as soon as possible.</p>
<p class="m-b-0 text-danger m-t-15" v-if="false">由于义乌船期不稳定建议发广州仓库<br>Due to unexpected shipping delays for Yiwu warehouse, you may select an alternative warehouse.</p>
<p class="m-b-0 text-danger m-t-15" v-if="parameters.warehouse_id === 4">由于义乌船期不稳定建议发广州仓库<br>Due to unexpected shipping delays for Yiwu warehouse, you may select an alternative warehouse.</p>
</div>
@@ -100,17 +100,33 @@
</modal-component>
</div>
</div>
<div class="row text-center parentContainer m-t-10" v-if="!item.shippng_transaction && item.order && item.order.company_module.billingAddress && $store.getters.isSuperAdmin && ['Pending Invoice', 'Pending Approval'].includes(invoice_status)" >
<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 :data="item.order.address" section="editBillingAddress"></address-form-component>
<div class="row text-center parentContainer m-t-10" v-if="['Pending Invoice', 'Pending Approval'].includes(invoice_status)" >
<div class="col">
<div class="row" v-if="!item.order.company_module.billingAddress">
<div class="col">
<div>
<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>
</div>
</modal-component>
<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 :data="item.order.company_module.billingAddress" section="editBillingAddress"></address-form-component>
</div>
</div>
</modal-component>
</div>
</div>
</div>
</div>
</div>
</div>
@@ -0,0 +1,90 @@
<template>
<div class="row" >
<div class="col">
<loading-component v-if="isLoading"></loading-component>
<div class="row" v-if="!isLoading">
<div class="col">
<div class="row m-b-15">
<div class="col-8 p-r-0">
<div class="row">
<div class="col p-r-0">
<div class="form-group no-margin form-group-default b-rad-none">
<label class="text-primary">Payment Due Days</label>
<input type="text" class="form-control" v-model.trim="parameters.due" />
</div>
</div>
<div class="col-auto">
<div class=" no-margin">
<input type="checkbox" checked="" value="0" id="checkbox2" v-model.trim="parameters.segment">
<label for="checkbox2 bold no-margin">Credit terms</label>
</div>
</div>
</div>
</div>
<div class="col p-l-0">
<div class="btn btn-primary b-rad-none" @click="fetchPaymentList()">
<i class="fa fa-filter lh-40"></i>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import LoadingComponent from "../../general/elements/LoadingComponent";
export default {
components: {LoadingComponent},
props: {
endpoint: {
type: String,
required: true
},
},
data(){
return {
section: 'pendingPaymentSection',
isLoading: false,
data: null,
parameters: {
due: '',
segment: false
},
}
},
validations: {
due: {},
},
methods: {
fetchPaymentList(){
this.$store.dispatch('reloadList', {name: this.section});
this.$store.dispatch('updateListQueue', {name: this.section, page:1, filters: {per_page:5, has_invoice_status_in:[2], payment_day:this.parameters.due, credit_term:this.parameters.segment, order_by: {column: 'updated_at', DESC: true}}});
//this.$store.dispatch('toggleSection', {name: this.section, status: true});
//this.$store.dispatch('updateListQueue', {name: this.section, page:1, filters: {per_page:5, group_by: 'transactions.id', payment_day:this.due,has_invoice_status_in:[2] /*,credit_term:[0.0]*/ }});
//let a = this.$store.getters.getListData('pendingPaymentSection');
//console.log(a);
// this.$store.dispatch('crudRequest', {endpoint: this.endpoint, method: 'get',parameters:{name: this.section, page:1, filters: {per_page:5, group_by: 'transactions.id', payment_day:this.due,has_invoice_status_in:[2] /*,credit_term:[0.0]*/ }}}).then(response => {
// console.log(response);
// let success = response.ok;
// response.json().then(response => {
// if(!success){return;}
// this.$store.dispatch('completeList', {name: this.section, data: a})
// });
//});
},
}
}
</script>
@@ -120,7 +120,8 @@
</div>
<div class="row tabsContainer tabContent hide" tab-name="pendingPayment">
<div class="col">
<list-component section="pendingPaymentSection" :endpoint="route('api.packing_list.list')" :options="{has_invoice_status_in: [2]}">
<payment-filter-component :endpoint="route('api.packing_list.list')" :data="data"></payment-filter-component>
<list-component section="pendingPaymentSection" :endpoint="route('api.packing_list.list')" :options="{has_invoice_status_in: [2], packing_list_ordered_by_invoice_date: true}">
<template slot="list" slot-scope="{data}">
<admin-payments-billing-component :data="data" invoice_status="Pending Payment" section="pendingPaymentSection" ></admin-payments-billing-component>
</template>
@@ -0,0 +1,8 @@
@extends('emails.layout.base')
@section('content')
<h4 style="font-size: 1em;">Hello, {{ $user->name }}</h4>
<p style="font-size: 0.9em">We wanted to send you an update on the recent shipment for you order no. <a href="{{ route('order.show', $packingList->owner->reference) }}">{{ $packingList->owner->reference }}</a> you have placed with us. We've just learned that your shipment has just departed from china's port and is estimated to arrive on {{ $packingList->containers()->first()->transports()->first()->schedules()->where('status', \App\Classes\ValueObjects\Constants\ApprovalStatus::APPROVED)->first()->eta->format('d-m-Y') }}.</p>
<p style="margin-top: 20px; font-size: 0.8em">Meanwhile, we would appreciate if you could make the payment as soon as possible so we can deliver your packages as soon as the shipment arrives. please <a href="{{ route('order.show', $packingList->owner->reference) }}">click here</a> to pay your invoice.</p>
<div style="margin-top: 20px;"><small style="font-size: 0.7em">If you wish to ask any additional questions, kindly contact us at our live chat from your account's <a href="{{ route('dashboard') }}">dashboard</a>.</small></div>
@endsection
@@ -0,0 +1,12 @@
@extends('emails.layout.base')
@section('content')
@php
$schedule = $packingList->containers()->first()->transports()->first()->schedules()->where('status', \App\Classes\ValueObjects\Constants\ApprovalStatus::APPROVED)->first();
@endphp
<h4 style="font-size: 1em;">Hello, {{ $user->name }}</h4>
<p style="font-size: 0.9em">Attached is the invoice concerning order no. {{$packingList->owner->reference}}. If the attached file isn't loading, please <a href="{{ route('order.show', $packingList->owner->reference) }}">click here</a> to access your invoice.</p>
<p style="margin-top: 30px; font-size: 0.8em">We would like to also inform you that your packages have been loaded into the container and is estimated to depart on: <span style="color: green; font-weight: bold">{{$schedule->etd->format('d-m-Y')}}</span> and is estimated to arrive on <span style="color: green; font-weight: bold">{{$schedule->eta->format('d-m-Y')}}</span>.</p>
<p style="margin-top: 15px; font-size: 0.8em">We appreciate you choosing us here at CIEF Worldwide to fulfill your shipping needs. We look forward to doing business with you again in the future.</p>
<div style="margin-top: 20px;"><small style="font-size: 0.7em">If you wish to ask any additional questions, kindly contact us at our live chat from your account's <a href="{{ route('dashboard') }}">dashboard</a>.</small></div>
@endsection
@@ -0,0 +1,14 @@
@extends('emails.layout.base')
@section('content')
<h4 style="font-size: 1em;">Hello, {{ $user->name }}</h4>
<p style="font-size: 0.9em">We wanted to send you an update on the recent shipment for you order no. <a href="{{ route('order.show', $packingList->owner->reference) }}">{{ $packingList->owner->reference }}</a> you have placed with us. We've just learned that there has been a shipping delay from the shipping liner, and as a result your packages will arrive a few days later the estimated date we gave you when we shipped your order. The new estimated date for arrival will be {{ $packingList->containers()->first()->transports()->first()->schedules()->where('status', \App\Classes\ValueObjects\Constants\ApprovalStatus::APPROVED)->first()->eta->format('d-m-Y') }}.</p>
<p style="margin-top: 30px; font-size: 0.8em">We're very sorry that you are experiencing this delay. and we wanted to let you know as soon as we learned about it. We are working directly with the shipping liner to minimize the impact, but we don't want you to worry your order is still on its way!</p>
<p style="margin-top: 20px; font-size: 0.8em">Recently shipping liner facing very frequent delay, it's better to estimate longer ETA while purchase to avoid any inconvenience causes.</p>
@if($packingList->transactions()->whereHas('transactions', function ($query){
return $query->where('type', \App\Classes\ValueObjects\Constants\TransactionType::SHIPPING_INVOICE)->where('status', '=', 2);
})->get())
<p style="margin-top: 20px; font-size: 0.8em">Meanwhile, we would appreciate if you could make the payment as soon as possible so we can deliver your packages as soon as the shipment arrives. please <a href="{{ route('order.show', $packingList->owner->reference) }}">click here</a> to pay your invoice.</p>
@endif
<div style="margin-top: 20px;"><small style="font-size: 0.7em">If you wish to ask any additional questions, kindly contact us at our live chat from your account's <a href="{{ route('dashboard') }}">dashboard</a>.</small></div>
@endsection
+89 -86
View File
@@ -1,49 +1,52 @@
@extends('layouts.base_portal')
@section('inner_content')
<div class="row m-b-15" v-if="false" v-show="!$store.getters.isShowing('createContainerFormSection')">
<div class="row" :class="[{'d-flex': $store.getters.isAdmin}]" v-if="$store.getters.isAdmin">
<div class="col">
<div data-type="createContainer" class="btn btn-sm btn-primary all-caps b-rad-none pointer m-l-5 rounded btn-lg" @click="$store.dispatch('toggleSection', {name: 'createContainerFormSection', status: true})"><i class="fa fa-plus m-r-10"></i>Add Container</div>
</div>
</div>
<div class="row m-b-15" v-if="false" v-show="!$store.getters.isShowing('createContainerFormSection')">
<div class="col">
<div data-type="createContainer" class="btn btn-sm btn-primary all-caps b-rad-none pointer m-l-5 rounded btn-lg" @click="$store.dispatch('toggleSection', {name: 'createContainerFormSection', status: true})"><i class="fa fa-plus m-r-10"></i>Add Container</div>
</div>
</div>
<container-search-component section="containerListSection"></container-search-component>
<create-load-container-form-component section="containerListSection" v-show="$store.getters.isShowing('createContainerFormSection')"></create-load-container-form-component>
<div class="row tabsContainer" v-show="!$store.getters.isShowing('createContainerFormSection') && !$store.getters.isShowing('searchContainerSection')">
<div class="col no-padding">
<div class="row m-l-0 m-r-0">
<div class="col col-md-4 m-r-5">
<div class="row justify-content-end">
<div class="col">
<div class="row fs-12 text-center">
<div class="col p-t-20 p-b-20 bg-master-lighter tabButton active" tab-name="active">
<div class="row justify-content-center m-b-5">
<div class="col-auto">
<img src="https://img.icons8.com/dotty/35/000000/cargo-ship.png"/>
<container-search-component section="containerListSection"></container-search-component>
<create-load-container-form-component section="containerListSection" v-show="$store.getters.isShowing('createContainerFormSection')"></create-load-container-form-component>
<div class="row tabsContainer" v-show="!$store.getters.isShowing('createContainerFormSection') && !$store.getters.isShowing('searchContainerSection')">
<div class="col no-padding">
<div class="row m-l-0 m-r-0">
<div class="col col-md-4 m-r-5">
<div class="row justify-content-end">
<div class="col">
<div class="row fs-12 text-center">
<div class="col p-t-20 p-b-20 bg-master-lighter tabButton active" tab-name="active">
<div class="row justify-content-center m-b-5">
<div class="col-auto">
<img src="https://img.icons8.com/dotty/35/000000/cargo-ship.png"/>
</div>
</div>
<div class="row">
<div class="col">
<div class="fs-12 m-t-5 all-caps">Active</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="fs-12 m-t-5 all-caps">Active</div>
</div>
</div>
</div>
<div class="col d-none d-md-inline m-l-5">
<div class="row justify-content-end">
<div class="col">
<div class="row fs-12 text-center">
<div class="col p-t-20 p-b-20 bg-master-lighter tabButton" tab-name="arrived">
<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;"><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 fill="#000000"><path d="M86.06719,12.9c-0.25976,-0.00731 -0.5187,0.03252 -0.76426,0.11758l-68.8,23.65c-0.86858,0.29776 -1.45225,1.11422 -1.45293,2.03242v12.9c-0.00043,0.68443 0.325,1.32819 0.8764,1.73365c0.5514,0.40547 1.2629,0.5242 1.91608,0.31977l1.50752,-0.47031v99.46689h19.35h10.75h36.55h2.15h34.4h12.9h17.2v-99.46689l1.50752,0.47031c0.65319,0.20444 1.36468,0.0857 1.91608,-0.31977c0.5514,-0.40547 0.87683,-1.04922 0.8764,-1.73365v-12.9c-0.00068,-0.9182 -0.58435,-1.73466 -1.45293,-2.03242l-68.8,-23.65c-0.20291,-0.07043 -0.41523,-0.11007 -0.62988,-0.11758zM86,17.32178l66.65,22.91094v8.44043l-7.95752,-2.48174c-0.27786,-0.09509 -0.57226,-0.13224 -0.86504,-0.10918l-0.21416,-0.22676l-0.74326,-0.13437l-1.72168,0.86504l-0.34014,1.89385l1.31436,1.41094l0.67607,0.11758c0.18673,0.12653 0.3922,0.22289 0.60889,0.28555l4.94248,1.54531v96.51064h-10.75v-86h-103.2v86h-10.75v-96.51484l4.94248,-1.54531c0.75045,-0.21514 1.32533,-0.82012 1.50193,-1.58056c0.1766,-0.76044 -0.07284,-1.55685 -0.65168,-2.08069c-0.57883,-0.52383 -1.39612,-0.69278 -2.13521,-0.44139l-7.95752,2.48594v-8.44043zM85.40791,28.13477l-1.72168,0.86084l-0.34014,1.89805l1.31855,1.40674l0.74326,0.13437l1.72588,-0.86504l0.33594,-1.89385l-1.31436,-1.40674zM93.61738,30.33096l-1.72168,0.86084l-0.34014,1.89805l1.31436,1.40674l0.74746,0.13437l1.72168,-0.86504l0.34014,-1.89385l-1.31436,-1.40674zM77.20264,30.70049l-1.72588,0.86084l-0.33594,1.89805l1.31436,1.40674l0.74746,0.13438l1.72168,-0.86504l0.34014,-1.89385l-1.31856,-1.40674zM101.82686,32.89668l-1.72168,0.86084l-0.34014,1.89805l1.31436,1.40674l0.74746,0.13437l1.72168,-0.86504l0.34014,-1.89385l-1.31436,-1.40674zM68.99316,33.26621l-1.72168,0.86084l-0.34014,1.89805l1.31436,1.40674l0.74746,0.13438l1.72168,-0.86504l0.34014,-1.89385l-1.31855,-1.40674zM110.03633,35.4624l-1.72588,0.86084l-0.33594,1.89805l1.31436,1.40674l0.74746,0.13437l1.72168,-0.86504l0.34014,-1.89385l-1.31855,-1.40674zM60.78369,35.83193l-1.72168,0.86084l-0.34014,1.89805l1.31436,1.40674l0.74746,0.13438l1.72168,-0.86504l0.34014,-1.89385l-1.31436,-1.41094zM118.2416,38.02812l-1.72168,0.86084l-0.34014,1.89805l1.31856,1.40674l0.74326,0.13437l1.72588,-0.86504l0.33594,-1.89385l-1.31436,-1.41094zM52.57422,38.39766l-1.72168,0.86084l-0.34014,1.89805l1.31855,1.40674l0.74326,0.13438l1.72168,-0.86504l0.34014,-1.89805l-1.31436,-1.40674zM126.45107,40.59385l-1.72168,0.86084l-0.34014,1.89805l1.31855,1.40674l0.74326,0.13438l1.72168,-0.86504l0.34014,-1.89805l-1.31436,-1.40674zM44.36895,40.95918l-1.72588,0.86504l-0.33594,1.89805l1.31436,1.40674l0.74746,0.13018l1.72168,-0.86084l0.34014,-1.89805l-1.31855,-1.40674zM134.66055,43.15537l-1.72168,0.86504l-0.34014,1.89805l1.31436,1.40674l0.74746,0.13018l1.72168,-0.86084l0.34014,-1.89805l-1.31436,-1.40674zM36.15947,43.5249l-1.72168,0.86504l-0.34014,1.89385l1.31436,1.41094l0.74746,0.13018l1.72168,-0.86084l0.34014,-1.89805l-1.31856,-1.40674zM38.7,66.65h94.6v81.7h-10.75v-34.4h-17.2v-34.4h-38.7v2.15v32.25h-17.2v2.15v32.25h-10.75zM70.95,83.85h30.1v30.1h-12.9h-2.15h-15.05zM53.75,118.25h12.9h17.2v30.1h-30.1zM88.15,118.25h17.2h12.9v30.1h-30.1z"></path></g></g></svg>
</div>
</div>
<div class="row">
<div class="col">
<div class="fs-12 m-t-5 all-caps">Un-stuffed</div>
<div class="col d-none d-md-inline m-l-5">
<div class="row justify-content-end">
<div class="col">
<div class="row fs-12 text-center">
<div class="col p-t-20 p-b-20 bg-master-lighter tabButton" tab-name="arrived">
<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;"><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 fill="#000000"><path d="M86.06719,12.9c-0.25976,-0.00731 -0.5187,0.03252 -0.76426,0.11758l-68.8,23.65c-0.86858,0.29776 -1.45225,1.11422 -1.45293,2.03242v12.9c-0.00043,0.68443 0.325,1.32819 0.8764,1.73365c0.5514,0.40547 1.2629,0.5242 1.91608,0.31977l1.50752,-0.47031v99.46689h19.35h10.75h36.55h2.15h34.4h12.9h17.2v-99.46689l1.50752,0.47031c0.65319,0.20444 1.36468,0.0857 1.91608,-0.31977c0.5514,-0.40547 0.87683,-1.04922 0.8764,-1.73365v-12.9c-0.00068,-0.9182 -0.58435,-1.73466 -1.45293,-2.03242l-68.8,-23.65c-0.20291,-0.07043 -0.41523,-0.11007 -0.62988,-0.11758zM86,17.32178l66.65,22.91094v8.44043l-7.95752,-2.48174c-0.27786,-0.09509 -0.57226,-0.13224 -0.86504,-0.10918l-0.21416,-0.22676l-0.74326,-0.13437l-1.72168,0.86504l-0.34014,1.89385l1.31436,1.41094l0.67607,0.11758c0.18673,0.12653 0.3922,0.22289 0.60889,0.28555l4.94248,1.54531v96.51064h-10.75v-86h-103.2v86h-10.75v-96.51484l4.94248,-1.54531c0.75045,-0.21514 1.32533,-0.82012 1.50193,-1.58056c0.1766,-0.76044 -0.07284,-1.55685 -0.65168,-2.08069c-0.57883,-0.52383 -1.39612,-0.69278 -2.13521,-0.44139l-7.95752,2.48594v-8.44043zM85.40791,28.13477l-1.72168,0.86084l-0.34014,1.89805l1.31855,1.40674l0.74326,0.13437l1.72588,-0.86504l0.33594,-1.89385l-1.31436,-1.40674zM93.61738,30.33096l-1.72168,0.86084l-0.34014,1.89805l1.31436,1.40674l0.74746,0.13437l1.72168,-0.86504l0.34014,-1.89385l-1.31436,-1.40674zM77.20264,30.70049l-1.72588,0.86084l-0.33594,1.89805l1.31436,1.40674l0.74746,0.13438l1.72168,-0.86504l0.34014,-1.89385l-1.31856,-1.40674zM101.82686,32.89668l-1.72168,0.86084l-0.34014,1.89805l1.31436,1.40674l0.74746,0.13437l1.72168,-0.86504l0.34014,-1.89385l-1.31436,-1.40674zM68.99316,33.26621l-1.72168,0.86084l-0.34014,1.89805l1.31436,1.40674l0.74746,0.13438l1.72168,-0.86504l0.34014,-1.89385l-1.31855,-1.40674zM110.03633,35.4624l-1.72588,0.86084l-0.33594,1.89805l1.31436,1.40674l0.74746,0.13437l1.72168,-0.86504l0.34014,-1.89385l-1.31855,-1.40674zM60.78369,35.83193l-1.72168,0.86084l-0.34014,1.89805l1.31436,1.40674l0.74746,0.13438l1.72168,-0.86504l0.34014,-1.89385l-1.31436,-1.41094zM118.2416,38.02812l-1.72168,0.86084l-0.34014,1.89805l1.31856,1.40674l0.74326,0.13437l1.72588,-0.86504l0.33594,-1.89385l-1.31436,-1.41094zM52.57422,38.39766l-1.72168,0.86084l-0.34014,1.89805l1.31855,1.40674l0.74326,0.13438l1.72168,-0.86504l0.34014,-1.89805l-1.31436,-1.40674zM126.45107,40.59385l-1.72168,0.86084l-0.34014,1.89805l1.31855,1.40674l0.74326,0.13438l1.72168,-0.86504l0.34014,-1.89805l-1.31436,-1.40674zM44.36895,40.95918l-1.72588,0.86504l-0.33594,1.89805l1.31436,1.40674l0.74746,0.13018l1.72168,-0.86084l0.34014,-1.89805l-1.31855,-1.40674zM134.66055,43.15537l-1.72168,0.86504l-0.34014,1.89805l1.31436,1.40674l0.74746,0.13018l1.72168,-0.86084l0.34014,-1.89805l-1.31436,-1.40674zM36.15947,43.5249l-1.72168,0.86504l-0.34014,1.89385l1.31436,1.41094l0.74746,0.13018l1.72168,-0.86084l0.34014,-1.89805l-1.31856,-1.40674zM38.7,66.65h94.6v81.7h-10.75v-34.4h-17.2v-34.4h-38.7v2.15v32.25h-17.2v2.15v32.25h-10.75zM70.95,83.85h30.1v30.1h-12.9h-2.15h-15.05zM53.75,118.25h12.9h17.2v30.1h-30.1zM88.15,118.25h17.2h12.9v30.1h-30.1z"></path></g></g></svg>
</div>
</div>
<div class="row">
<div class="col">
<div class="fs-12 m-t-5 all-caps">Un-stuffed</div>
</div>
</div>
</div>
</div>
</div>
@@ -53,60 +56,60 @@
</div>
</div>
</div>
</div>
</div>
<div class="col-2 ml-auto d-none d-md-inline">
<div class="row justify-content-end">
<div class="col">
<div class="row fs-12 text-center">
<div class="col p-t-20 p-b-20 bg-master-lighter tabButton" tab-name="complete">
<div class="row justify-content-center m-b-5">
<div class="col-auto">
<img src="https://img.icons8.com/dotty/35/000000/shipped.png"/>
</div>
</div>
<div class="row">
<div class="col">
<div class="fs-12 m-t-5 all-caps">Delivered</div>
<div class="col-2 ml-auto d-none d-md-inline">
<div class="row justify-content-end">
<div class="col">
<div class="row fs-12 text-center">
<div class="col p-t-20 p-b-20 bg-master-lighter tabButton" tab-name="complete">
<div class="row justify-content-center m-b-5">
<div class="col-auto">
<img src="https://img.icons8.com/dotty/35/000000/shipped.png"/>
</div>
</div>
<div class="row">
<div class="col">
<div class="fs-12 m-t-5 all-caps">Delivered</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row no-margin">
<div class="col bg-master-lightest p-1 p-sm-4">
<div class="row tabsContainer tabContent" tab-name="active">
<div class="col">
<list-component section="activeContainerListSection" :endpoint="route('api.packing_list.container.list')" :options="{'per_page': 5, 'status_in': [1], order_by: {column: 'loading_date', DESC: true}}">
<template slot="list" slot-scope="{data}">
<container-component section="activeContainerListSection" :data="data"></container-component>
</template>
</list-component>
</div>
</div>
<div class="row tabsContainer tabContent hide" tab-name="arrived">
<div class="col">
<list-component section="arrivedContainerListSection" :endpoint="route('api.packing_list.container.list')" :options="{'per_page': 5, 'status_in': [3], 'has_pending_delivery': true, order_by: {column: 'loading_date', DESC: true}}">
<template slot="list" slot-scope="{data}">
<container-component section="arrivedContainerListSection" :data="data"></container-component>
</template>
</list-component>
</div>
</div>
<div class="row tabsContainer tabContent hide" tab-name="complete">
<div class="col">
<list-component section="completeContainerListSection" :endpoint="route('api.packing_list.container.list')" :options="{'per_page': 5, 'status_in': [3], 'has_pending_delivery': false, order_by: {column: 'loading_date', DESC: true}}">
<template slot="list" slot-scope="{data}">
<container-component section="completeContainerListSection" :data="data"></container-component>
</template>
</list-component>
<div class="row no-margin">
<div class="col bg-master-lightest p-1 p-sm-4">
<div class="row tabsContainer tabContent" tab-name="active">
<div class="col">
<list-component section="activeContainerListSection" :endpoint="route('api.packing_list.container.list')" :options="{'per_page': 5, 'status_in': [1], order_by: {column: 'loading_date', DESC: true}}">
<template slot="list" slot-scope="{data}">
<container-component section="activeContainerListSection" :data="data"></container-component>
</template>
</list-component>
</div>
</div>
<div class="row tabsContainer tabContent hide" tab-name="arrived">
<div class="col">
<list-component section="arrivedContainerListSection" :endpoint="route('api.packing_list.container.list')" :options="{'per_page': 5, 'status_in': [3], 'has_pending_delivery': true, order_by: {column: 'loading_date', DESC: true}}">
<template slot="list" slot-scope="{data}">
<container-component section="arrivedContainerListSection" :data="data"></container-component>
</template>
</list-component>
</div>
</div>
<div class="row tabsContainer tabContent hide" tab-name="complete">
<div class="col">
<list-component section="completeContainerListSection" :endpoint="route('api.packing_list.container.list')" :options="{'per_page': 5, 'status_in': [3], 'has_pending_delivery': false, order_by: {column: 'loading_date', DESC: true}}">
<template slot="list" slot-scope="{data}">
<container-component section="completeContainerListSection" :data="data"></container-component>
</template>
</list-component>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@endsection
@endsection
+9 -9
View File
@@ -216,6 +216,15 @@
</div>
</div>
</div>
<div class="row tabsContainer hide tabContent" tab-name="debtor">
<div class="col-12 col-md-6 p-r-0" v-if="$store.getters.isSuperAdmin || ([2251]).includes($store.getters.getUserId)" >
<div class="row">
<div class="col">
<upload-debtor-excel-component section="uploadDebtorExcelSection"></upload-debtor-excel-component>
</div>
</div>
</div>
</div>
<template v-if="$store.getters.isSuperAdmin">
<div class="row tabsContainer hide tabContent" tab-name="team">
<div class="col">
@@ -427,15 +436,6 @@
</div>
</div>
</div>
<div class="row tabsContainer hide tabContent" tab-name="debtor">
<div class="col-12 col-md-6 p-r-0" v-if="$store.getters.isSuperAdmin || ([2251]).includes($store.getters.getUserId)">
<div class="row">
<div class="col">
<upload-debtor-excel-component section="uploadDebtorExcelSection"></upload-debtor-excel-component>
</div>
</div>
</div>
</div>
</template>
</div>
</div>
+2 -2
View File
@@ -8,6 +8,6 @@
</script>
<script type="text/javascript">window.$crisp=[];window.CRISP_WEBSITE_ID="665dcd41-1edf-4451-8cb9-f1cf9ed35e15";(function(){d=document;s=d.createElement("script");s.src="https://client.crisp.chat/l.js";s.async=1;d.getElementsByTagName("head")[0].appendChild(s);})();</script>
<script src="{{ asset('js/vendor.js') }}" type="text/javascript"></script>
<script src="{{mix('vue/app.js')}}"></script>
<script src="@if (env('APP_ENV') === 'local') {{asset('vue/app.js')}} @else {{mix('vue/app.js')}} @endif"></script>
<script src="{{ asset('js/site.js') }}" type="text/javascript"></script>
{{--END VENDOR JS--}}
{{--END VENDOR JS--}}
+1
View File
@@ -8,6 +8,7 @@ Route::group(['prefix' => 'company', 'as' => 'company.', 'namespace' => 'Compani
Route::post('/create', 'CreateCompanyController@create')->name('create');
Route::put('/update/{id}', 'UpdateCompanyController@update')->name('update');
Route::delete('/delete/{id}', 'DeleteCompanyController@destroy')->name('delete');
Route::put('/name/update/{id}', 'UpdateCompanyNameController@rename')->name('update.name');
Route::post('/team/create', 'AddNewMemberController@create')->name('team.create');
+238 -3
View File
@@ -1,19 +1,31 @@
<?php
use App\Classes\Exceptions\InternalServerErrorException;
use App\Classes\Jobs\FetchContainersStatusUpdateFromVTPortalJob;
use App\Classes\Jobs\FetchDeliveryListFromVTPortalJob;
use App\Classes\Jobs\FetchLoadedContainersFromVTPortalJob;
use App\Classes\Jobs\FetchOrdersFromYDPortalJob;
use App\Classes\Jobs\FetchPackingListFromVTPortalJob;
use App\Classes\Jobs\FetchWarehouseReceiveListFromVTPortalJob;
use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject;
use App\Classes\Modules\Orders\Processors\UpdateDoFromVTPortalProcessor;
use App\Classes\Modules\Orders\Processors\UpdateDoFromYDPortalProcessor;
use App\Classes\Modules\PackingLists\Processors\FetchOrderListsFromYdPortalProcessor;
use App\Classes\Modules\PackingLists\Processors\FetchPackingListFromVTPortalProcessor;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\DocumentType;
use App\Classes\ValueObjects\Constants\OrderRoleTypes;
use App\Classes\ValueObjects\Constants\PackageType;
use App\Models\CompanyConnection;
use App\Models\CompanyModule;
use App\Models\Document;
use App\Models\PackingList;
use Illuminate\Support\Facades\Crypt;
use App\Models\Container;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Route;
use Meneses\LaravelMpdf\Facades\LaravelMpdf;
/*
|--------------------------------------------------------------------------
@@ -305,6 +317,7 @@ Route::get('/export/on-hold-packing-list', 'Exports\ExportPendingArrangementPack
Route::get('/export/arrived-parcel', 'Exports\ExportArrivedParcelController@export')->name('packing_list.arrived_parcel.export');
Route::get('/export/parcel-summary', 'Exports\ExportArrivedParcelController@summary');
Route::get('/export/parcel-postcode', 'Exports\ExportParcelPostcodesController@export');
Route::get('/export/{year}/customer-total-order', 'Exports\ExportCustomersToExcelController@totalOrders');
Route::get('/settings', function () {
return view('pages.settings');
@@ -428,9 +441,9 @@ Route::get('/export/payment-transactions/f614e339d7058904a831aad742e24d55', 'Exp
Route::get('/delayed_container/customers', function(){
$containers = Container::whereHas('transports', function($query){
return $query->whereHas('Schedules', function($query){
return $query->where('etd', '>', \Carbon\Carbon::parse('15-10-2022'));
});
return $query->whereHas('Schedules', function($query){
return $query->where('etd', '>', \Carbon\Carbon::parse('15-10-2022'));
});
})->get();
$orders = $containers->map(function($container){
@@ -448,3 +461,225 @@ Route::get('/delayed_container/customers', function(){
});
Route::get('/container/billing/{month}/{year}', function($month, $year){
$containers = Container::whereDate('loading_date', '>=', \Carbon\Carbon::parse('01-'.$month.'-'.$year))->whereDate('loading_date', '<', \Carbon\Carbon::parse('01-'.$month.'-'.$year)->addMonth())->get();
$totalBillable = 0;
$billed = 0;
$totalBilled = 0;
$totalPaid = 0;
$basePrice = 315;
$bigParcelDiscount = -15;
$yiwuCost = 15;
$discount = -20;
$yiwuDiscount = -45;
$outstationStates = [8, 3, 16, 10];
foreach($containers as $container) {
$containerTotalBillable = 0;
$containerBilled = 0;
$containerTotalBilled = 0;
$containerTotalPaid = 0;
$containerCost = 0;
$packingLists = $container->packingLists;
$totalBillable += count($packingLists);
$containerTotalBillable += count($packingLists);
echo '<h3>'.$container->reference.' ('.$container->loading_date->format('d-m-Y').')</h3>';
foreach ($packingLists as $packingList) {
$invoice = $packingList->transactions()
->where('type', \App\Classes\ValueObjects\Constants\TransactionType::SHIPPING_INVOICE)->whereIn('status', [\App\Classes\ValueObjects\Constants\ApprovalStatus::APPROVED, \App\Classes\ValueObjects\Constants\ApprovalStatus::COMPLETED])
->first();
$warehouseList = PackingList::where('reference', $packingList->reference)->where('type', 1)->first();
if($warehouseList){
$packing_list_drop_date = $warehouseList->transports->first()->drop_date;
} else {
echo '<------------- can\'t find arrival date -------------->';
}
$order = $packingList->owner;
$address = $order->addresses()->where('status', \App\Classes\ValueObjects\Constants\ApprovalStatus::APPROVED)->first();
$warehouseId = $order->orderRoles()->where('role_id', OrderRoleTypes::ORIGIN_WAREHOUSE)->first()->company_module_id;
$cbm = round($packingList->packages->where('type', '!=', PackageType::OVER_WEIGHT)->sum(function($package) {
return ($package->width / 100) * ($package->height / 100) *($package->length / 100) * ($package->quantity);
}), 2);
$over_weight_cbm = round($packingList->packages->where('type', PackageType::OVER_WEIGHT)->sum(function($package) {
return ($package->width / 100) * ($package->height / 100) *($package->length / 100) * ($package->quantity);
}), 2);
$price = $basePrice;
if($warehouseId === 2358){
$price += $yiwuCost;
if($packing_list_drop_date >= \Carbon\Carbon::parse('19-9-2022')){
$price += $yiwuDiscount;
}
} else {
if($cbm >= 2 && in_array($address->state_id, [4, 15])){
$price += $bigParcelDiscount;
}
if($packing_list_drop_date >= \Carbon\Carbon::parse('19-9-2022')){
$price += $discount;
}
}
if(in_array($address->state_id,$outstationStates)) {
$price += 50;
}
$cbm = max($cbm, 0.3);
$cost = $price * ($cbm + $over_weight_cbm);
$containerCost += $cost;
if(in_array($address->state_id, [13, 14])) {
echo 'East Malaysia - ';
}
echo 'estimated cost: [QTY: '.($cbm + $over_weight_cbm).' | Unit Price: '.$price.' | Total: '.$cost.']';
echo '<br>';
if(!$invoice) {
echo '<p style="color: red"><a href="'.route('order.show', $order->reference).'" target="_blank">'.$packingList->reference .'</a> Warning: no billing</p>';
continue;
}
$payments = $invoice->transactions()
->where('type', \App\Classes\ValueObjects\Constants\TransactionType::PAYMENT)->whereIn('status', [\App\Classes\ValueObjects\Constants\ApprovalStatus::APPROVED, \App\Classes\ValueObjects\Constants\ApprovalStatus::COMPLETED])
->get();
$billed += 1;
$containerBilled += 1;
$totalBilled += $invoice->amount;
$containerTotalBilled += $invoice->amount;
$totalPaid += $payments->sum('amount');
$containerTotalPaid += $payments->sum('amount');
echo '<span style="color: '.(($invoice->amount - $payments->sum('amount')) < 0.01 ? 'green' : 'red').'"><p style="color: red"><a href="'.route('order.show', $order->reference).'" target="_blank">'.$packingList->reference .'</a> | Amount: '.$invoice->amount.' | Paid: '.$payments->sum('amount').' | Invoice Date: '.$invoice->created_at->format('d-m-Y'). (($invoice->amount - $payments->sum('amount')) < 0.01 ? '' : '('.$invoice->created_at->diffForHumans().')').'</span>';
echo '<br><br>';
}
echo '<h4>Container Invoices: '.$containerBilled.'/'.$containerTotalBillable.'</h4>';
echo '<h4>Billed Total: '.$containerTotalBilled.'</h4>';
echo '<h4>Total Paid: '.$containerTotalPaid.'</h4>';
echo '<h4>Outstanding: '.($totalBilled - $containerTotalPaid).'</h4>';
echo '<h4>Estimated Cost: '.$containerCost.'</h4>';
echo '<br><br><br>';
}
echo '<h2>Total Invoices: '.$billed.'/'.$totalBillable.'</h2>';
echo '<h2>Billed Total: '.$totalBilled.'</h2>';
echo '<h2>Total Paid: '.$totalPaid.'</h2>';
echo '<h2>Outstanding: '.($totalBilled - $totalPaid).'</h2>';
});
Route::get('/yd/fix', function(){
$packingLists = \App\Models\PackingList::where('type', \App\Classes\ValueObjects\Constants\PackingListType::SHIPPING_PACKING_LIST)->where('status', \App\Classes\ValueObjects\Constants\ApprovalStatus::APPROVED)->where('claimant_id', 2307)->get();
$i = 0;
echo count($packingLists).'<br><br>';
foreach ($packingLists as $packingList){
try {
(App()->make(UpdateDoFromYDPortalProcessor::class))->execute($packingList);
echo 'success'.'<br>';
} catch (\Exception $exception){
echo '<span style="color:red;">'.$packingList->reference.'</span>';
}
}
});
Route::get('/billplz/fix', function(){
$payments = \App\Models\Transaction::where('type', \App\Classes\ValueObjects\Constants\TransactionType::PAYMENT)->where('payment_method',\App\Classes\ValueObjects\Constants\PaymentMethodType::PAYMENT_GATEWAY)->get();
echo '<h3>fixed orders</h3>';
foreach ($payments as $payment){
$response = Http::withBasicAuth(config('billplz.api_key').':', '')->get(config('billplz.base_url').'/api/v3/bills/'.$payment->payment_reference);
if($response->successful()){
$data = $response->json();
$invoice = $payment->owner;
if(!$invoice){
continue;
}
$packingList = $invoice->owner;
$order = $packingList->owner;
$orderNumber = $order->reference;
if(!$data['paid'] && $payment->status === \App\Classes\ValueObjects\Constants\ApprovalStatus::APPROVED) {
echo '<br><span style="color: red">Fraude: <a href="'.route('order.show', $orderNumber).'" target="_blank">'.$orderNumber.'</a></span><br>';
continue;
}
if($data['paid']){
if($payment->status !== \App\Classes\ValueObjects\Constants\ApprovalStatus::APPROVED){
echo '<a href="'.route('order.show', $orderNumber).'" target="_blank">'.$orderNumber.'</a><br>';
}
$payment->status = \App\Classes\ValueObjects\Constants\ApprovalStatus::APPROVED;
$payment->save();
$invoice->status = \App\Classes\ValueObjects\Constants\ApprovalStatus::COMPLETED;
$invoice->save();
$packingList = $payment->owner->owner;
if(app()->environment('production')){
try {
(App()->make(UpdateDoFromVTPortalProcessor::class))->execute($packingList);
(App()->make(UpdateDoFromYDPortalProcessor::class))->execute($packingList);
} catch (\Exception $exception){
echo '<br><span style="color: red">Malformed Address: <a href="'.route('order.show', $orderNumber).'" target="_blank">'.$orderNumber.'</a></span><br>';
}
}
}
}else{
echo "billplz error";
}
}
});
Route::get('/invoices/fix', function(){
$orders = \App\Models\Order::whereIn('company_module_id', [294, 2703])->get();
foreach ($orders as $order){
$invoices = $order->transactions()->where('transactions.type', \App\Classes\ValueObjects\Constants\TransactionType::SHIPPING_INVOICE)->get();
foreach ($invoices as $invoice){
$invoice->documents()->delete();
$transaction_invoice_pdf = LaravelMpdf::loadView('pages.pdfs.shipping_invoice', ['invoice_transaction' => $invoice]);
$document_object = new DocumentObject(
DocumentType::SHIPPING_INVOICE,
[chunk_split('data:application/pdf;base64,'.base64_encode($transaction_invoice_pdf->output()))],
'',
ApprovalStatus::COMPLETED,
'shipping_invoice'
);
/** @var Document $document */
$document = (App()->make(\App\Classes\Modules\Documents\Services\CreatesDocument::class))->execute($invoice, $document_object);
(App()->make(\App\Classes\Modules\Documents\Services\CreatesFiles::class))->execute($document, $document_object);
}
}
});