Compare commits

..

11 Commits

Author SHA1 Message Date
edmondlang 834ea52a4f debug testing 2023-01-18 00:47:41 +08:00
edmondlang 551fb7deaa update search customer by email component - enable search by pressing enter 2023-01-16 00:03:28 +08:00
Dillon 2248e76bd4 Allow admin to search a customer by email address to open in new window 2023-01-11 22:44:04 +08: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
21 changed files with 345 additions and 202 deletions
@@ -0,0 +1,63 @@
<?php
namespace App\Classes\Modules\Accounts\ControllersLogic;
use App\Classes\Modules\Accounts\Services\FetchesUser;
use App\Classes\Modules\Accounts\Standards\Rules\CanFetchUser;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Http\Resources\UserCompanyResource;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class FetchUserByEmailLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Fetch Users',
'message' => 'You have successfully retrieved the user by email'
];
}
/** @var CanFetchUser */
private $canFetchUser;
/** @var FetchesUser */
private $fetchesUser;
/**
* FetchUserByEmailLogic constructor.
* @param CanFetchUser $canFetchUser
* @param FetchesUser $fetchessUser
*/
public function __construct(CanFetchUser $canFetchUser, FetchesUser $fetchesUser)
{
$this->canFetchUser = $canFetchUser;
$this->fetchesUser = $fetchesUser;
}
/**
* @param Request $request
* @return JsonResponse
* @throws ErrorException
*/
public function logic(Request $request) : JsonResponse
{
try {
$this->canFetchUser->passes();
$query = $this->fetchesUser->execute(['email' => $request->route('email')]);
return $this->resourceResponse(new UserCompanyResource($query));
} catch (\Exception $exception){
throw new ErrorException($exception->getMessage(), $exception->getCode());
}
}
}
@@ -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
];
}
}
@@ -1,11 +0,0 @@
<?php
namespace App\Classes\ValueObjects\Constants;
final class RouteType {
public const WEB = 1;
public const API = 2;
}
@@ -0,0 +1,22 @@
<?php
namespace App\Http\Controllers\Accounts;
use App\Classes\Modules\Accounts\ControllersLogic\FetchUserByEmailLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class FetchUserByEmailController
{
/**
* @param Request $request
* @param FetchUserByEmailLogic $logic
* @return JsonResponse
*/
public function fetch(Request $request, FetchUserByEmailLogic $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,6 +1,6 @@
<?php
namespace App\Http\Controllers\PackingLists\Containers;
namespace App\Http\Controllers\PackingLists\Packages;
use App\Classes\Modules\PackingLists\ControllersLogic\Containers\InboundCustomClearedLogic;
use Illuminate\Http\JsonResponse;
-2
View File
@@ -38,13 +38,11 @@ class Kernel extends HttpKernel
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\WebRouteLogs::class,
],
'api' => [
'throttle:300,1',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\ApiRouteLogs::class,
],
];
-64
View File
@@ -1,64 +0,0 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use App\Models\RouteLog;
use App\Classes\ValueObjects\Constants\RouteType;
use Illuminate\Support\Facades\Auth;
class ApiRouteLogs
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle(Request $request, Closure $next)
{
$ip_address = getenv('REMOTE_ADDR') == '::1' ? '127.0.0.1' : getenv('REMOTE_ADDR');
$url = urldecode($request->fullUrl());
$request_method = $request->method();
$platform = $request->header('sec-ch-ua-platform');
$browser = Str::after($request->header('sec-ch-ua'), 'Not?A_Brand";v="8", "Chromium";v="108", "');
$geo = unserialize(file_get_contents("http://www.geoplugin.net/php.gp?ip=$ip_address"));
$longitude = $geo["geoplugin_longitude"];
$latitude = $geo["geoplugin_latitude"];
$last_page = url()->previous();
$countryName = $geo["geoplugin_countryName"];
$user_id = Auth::user() ? Auth::user()->id : 0;
// if ($user_id != 0) {
// // $ip_address
// $webRouteLogWithSameIp = RouteLog::where('ip_address', $ip_address)->where('user_id', 0)->get();
// dd($webRouteLogWithSameIp);
// foreach($webRouteLogWithSameIp as $result){
// $result
// }
// }
$route_log = [
'user_id' => $user_id,
// 'ip_address' => $request->ip(),
'ip_address' => $ip_address,
'url' => $url,
'request_method' => $request_method,
'browser' => $browser,
'platform' => $platform,
'longitude' => $longitude,
'latitude' => $latitude,
'last_page' => $last_page,
'countryname' => $countryName,
'route_type' => RouteType::API,
];
RouteLog::create($route_log);
return $next($request);
}
}
-55
View File
@@ -1,55 +0,0 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use App\Models\RouteLog;
use App\Classes\ValueObjects\Constants\RouteType;
use Illuminate\Support\Facades\Auth;
class WebRouteLogs
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle(Request $request, Closure $next)
{
$ip_address = getenv('REMOTE_ADDR') == '::1' ? '127.0.0.1' : getenv('REMOTE_ADDR');
$url = $request->fullUrl();
$request_method = $request->method();
$platform = $request->header('sec-ch-ua-platform');
$browser = Str::after($request->header('sec-ch-ua'), 'Not?A_Brand";v="8", "Chromium";v="108", "');
$geo = unserialize(file_get_contents("http://www.geoplugin.net/php.gp?ip=$ip_address"));
$longitude = $geo["geoplugin_longitude"];
$latitude = $geo["geoplugin_latitude"];
$last_page = url()->previous();
$countryName = $geo["geoplugin_countryName"];
$route_log = [
'user_id' => Auth::user() ? Auth::user()->id : 0,
// 'ip_address' => $request->ip(),
'ip_address' => $ip_address,
'url' => $url,
'request_method' => $request_method,
'browser' => $browser,
'platform' => $platform,
'longitude' => $longitude,
'latitude' => $latitude,
'last_page' => $last_page,
'countryname' => $countryName,
'route_type' => RouteType::WEB,
];
// dd($route_log);
RouteLog::create($route_log);
return $next($request);
}
}
+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)
@@ -0,0 +1,26 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class UserCompanyResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'reference' => $this->companyModule()->first()->inviters()->withPivot('invitee_reference')->first()->pivot->invitee_reference,
'type' => (int) $this->type,
'status' => (int) $this->status,
'email' => $this->email
];
}
}
-25
View File
@@ -1,25 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class RouteLog extends Model
{
use HasFactory;
protected $fillable = [
'user_id',
'ip_address',
'url',
'request_method',
'browser',
'platform',
'longitude',
'latitude',
'last_page',
'countryname',
'route_type'
];
}
@@ -1,42 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateRouteLogsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('route_logs', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->unsigned();
$table->string('ip_address');
$table->string('url', 255);
$table->string('request_method');
$table->string('browser')->nullable();
$table->string('platform')->nullable();
$table->string('longitude')->nullable();
$table->string('latitude')->nullable();
$table->string('last_page')->nullable();
$table->string('countryname')->nullable();
$table->integer('route_type');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('route_logs');
}
}
@@ -0,0 +1,39 @@
<template>
<div class="row m-b-15 align-items-end">
<div class="col-auto">
<div class="row">
<div class="col">
<div class="font-heading fs-10 muted all-caps">Name</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="font-heading all-caps fs-11">{{this.item.name}}</div>
</div>
</div>
</div>
<div class="col-2 text-right">
<div class="row">
<div class="col">
<div class="font-heading fs-10 muted all-caps">Reference</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="font-heading all-caps fs-11">{{this.item.reference}}</div>
</div>
</div>
</div>
<div class="col-auto">
<a :href="route('customer.profile', this.item.reference)" target="_blank">
<button type="button" class="btn btn-xs btn-primary fs-11">Open in new tab</button>
</a>
</div>
</div>
</template>
<script>
import componentHandler from '../../../general/mixins/componentHandler';
export default {
mixins: [componentHandler]
}
</script>
@@ -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>
@@ -0,0 +1,82 @@
<template>
<div class="row" @keyup.enter="fetchReport">
<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">Email</label>
<input type="text" class="form-control" v-model="email" />
</div>
</div>
</div>
</div>
<div class="col p-l-0">
<div class="btn btn-primary b-rad-none" @click="fetchReport()">
<i class="fa fa-search lh-40"></i>
</div>
<div class="btn btn-secondary b-rad-none" @click="resetSearch()">
<i class="fa fa-remove lh-40"></i>
</div>
</div>
</div>
<div class="row" v-if="search">
<div class="col bg-white padding-25">
<p v-if="!userCompany">{{ message }}</p>
<loading-component v-if="isLoading"></loading-component>
<user-company-component v-if="userCompany" :data="userCompany"></user-company-component>
</div>
</div>
</div>
</div>
</template>
<script>
import LoadingComponent from "../../general/elements/LoadingComponent";
export default {
components: {LoadingComponent},
data(){
return {
section: 'searchUserCompanyByEmailSection',
isLoading: false,
search: false,
email: '',
userCompany: null,
message: 'Searching...'
}
},
validations: {
marking: {},
},
methods: {
fetchReport(){
this.isLoading = true;
this.search = true;
this.userCompany = null;
this.message = 'Searching...';
this.submit(route('api.account.user.company', this.email), 'get', this.section, false, false);
},
successHandler(response){
this.isLoading = false;
this.report = response.payload.data;
if(response.payload.data != undefined)
this.userCompany = response.payload.data;
else
this.message = 'Customer not found';
},
errorHandler(response){
this.isLoading = false;
this.userCompany = null;
this.message = 'Customer not found';
},
resetSearch() {
this.userCompany = null;
this.search = false;
this.email = '';
message: 'Searching...';
}
}
}
</script>
@@ -3,6 +3,7 @@
<div class="row" :class="[{'d-flex': $store.getters.isAdmin}]" v-if="$store.getters.isAdmin">
<div class="col">
<customer-activity-report-section-component></customer-activity-report-section-component>
<search-customer-by-email-component></search-customer-by-email-component>
<div class="row" v-show="!$store.getters.isShowing('customerActivityReportSection')">
<div class="col">
<customer-report-section-component></customer-report-section-component>
+1
View File
@@ -35,6 +35,7 @@ Route::group(['prefix' => 'account', 'namespace' => 'Accounts', 'as' => 'account
});
Route::group(['middleware' => 'valid.token', 'prefix' => 'user', 'as' => 'user.'], function () {
Route::get('/{email}', 'FetchUserByEmailController@fetch')->name('company');
Route::post('/show', 'FetchUserController@fetch')->name('show');
Route::get('/list', 'ListUsersController@list')->name('list');
Route::put('/update/{id}', 'UpdateUserController@update')->name('update');
+1 -1
View File
@@ -44,7 +44,7 @@ Route::group(['namespace' => 'PackingLists', 'as' => 'packing_list.', 'prefix' =
Route::get('/inbound-custom-cleared', 'InboundCustomClearedController@list')->name('list.inbound.custom.cleared');
Route::put('/switch-packing-list/{id}', 'SwitchPackagePackingListController@switch')->name('switch.packing_list');
Route::group(['namespace' => 'PackageItems', 'prefix' => 'item', 'as' => 'item.'], function () {
Route::group(['namespace' => 'Items', 'prefix' => 'item', 'as' => 'item.'], function () {
Route::get('/{id}/show', 'FetchPackageItemController@fetch')->name('show');
Route::get('/list', 'ListPackageItemsController@list')->name('list');
Route::post('/create', 'CreatePackageItemController@create')->name('create');
+1
View File
@@ -317,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');