fix load data dealer base on user with pivot or not
This commit is contained in:
@@ -4,10 +4,12 @@ namespace App\Http\Controllers;
|
|||||||
|
|
||||||
use App\Models\Dealer;
|
use App\Models\Dealer;
|
||||||
use App\Models\Menu;
|
use App\Models\Menu;
|
||||||
|
use App\Models\Role;
|
||||||
use App\Models\Transaction;
|
use App\Models\Transaction;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Models\Work;
|
use App\Models\Work;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
|
|
||||||
@@ -37,7 +39,21 @@ class AdminController extends Controller
|
|||||||
$month = $request->month;
|
$month = $request->month;
|
||||||
$dealer = $request->dealer;
|
$dealer = $request->dealer;
|
||||||
$year = $request->year;
|
$year = $request->year;
|
||||||
$dealer_datas = Dealer::all();
|
|
||||||
|
// Get dealers based on user role
|
||||||
|
$user = Auth::user();
|
||||||
|
$role = Role::with(['dealers' => function($query) {
|
||||||
|
$query->whereNull('dealers.deleted_at'); // Only active dealers
|
||||||
|
}])->find($user->role_id);
|
||||||
|
|
||||||
|
if($role && $this->isAdminRole($role) && $role->dealers->count() == 0) {
|
||||||
|
$dealer_datas = Dealer::all();
|
||||||
|
} else if($role) {
|
||||||
|
$dealer_datas = $role->dealers()->whereNull('dealers.deleted_at')->orderBy('name')->get();
|
||||||
|
} else {
|
||||||
|
$dealer_datas = collect();
|
||||||
|
}
|
||||||
|
|
||||||
$ajax_url = route('dashboard_data').'?month='.$month.'&year='.$year.'&dealer='.$dealer;
|
$ajax_url = route('dashboard_data').'?month='.$month.'&year='.$year.'&dealer='.$dealer;
|
||||||
// dd($ajax_url);
|
// dd($ajax_url);
|
||||||
return view('dashboard', compact('month','year', 'ajax_url', 'dealer', 'dealer_datas'));
|
return view('dashboard', compact('month','year', 'ajax_url', 'dealer', 'dealer_datas'));
|
||||||
@@ -72,16 +88,47 @@ class AdminController extends Controller
|
|||||||
$dealer_work_trx = DB::statement("SET @sql = NULL");
|
$dealer_work_trx = DB::statement("SET @sql = NULL");
|
||||||
$sql = "SELECT IF(work_id IS NOT NULL, GROUP_CONCAT(DISTINCT CONCAT('SUM(IF(work_id = \"', work_id,'\", qty,\"\")) AS \"',CONCAT(w.name, '|',w.id),'\"')), 's.work_id') INTO @sql FROM transactions t JOIN works w ON w.id = t.work_id WHERE month(t.date) = '". $month ."' and year(t.date) = '". $year ."' and t.deleted_at is null";
|
$sql = "SELECT IF(work_id IS NOT NULL, GROUP_CONCAT(DISTINCT CONCAT('SUM(IF(work_id = \"', work_id,'\", qty,\"\")) AS \"',CONCAT(w.name, '|',w.id),'\"')), 's.work_id') INTO @sql FROM transactions t JOIN works w ON w.id = t.work_id WHERE month(t.date) = '". $month ."' and year(t.date) = '". $year ."' and t.deleted_at is null";
|
||||||
|
|
||||||
if(isset($request->dealer) && $request->dealer != 'all') {
|
|
||||||
$sql .= " and t.dealer_id = '". $dealer ."'";
|
|
||||||
}
|
|
||||||
|
|
||||||
$dealer_work_trx = DB::statement($sql);
|
$dealer_work_trx = DB::statement($sql);
|
||||||
|
|
||||||
|
// Get dealers based on user role - only change this part
|
||||||
|
$user = Auth::user();
|
||||||
|
$role = Role::with(['dealers' => function($query) {
|
||||||
|
$query->whereNull('dealers.deleted_at'); // Only active dealers
|
||||||
|
}])->find($user->role_id);
|
||||||
|
|
||||||
|
if($role && $this->isAdminRole($role) && $role->dealers->count() == 0) {
|
||||||
|
$dealer_datas = Dealer::all();
|
||||||
|
} else if($role) {
|
||||||
|
$dealer_datas = $role->dealers()->whereNull('dealers.deleted_at')->orderBy('name')->get();
|
||||||
|
} else {
|
||||||
|
$dealer_datas = collect();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate that the requested dealer is allowed for this user
|
||||||
if(isset($request->dealer) && $request->dealer != 'all') {
|
if(isset($request->dealer) && $request->dealer != 'all') {
|
||||||
$dealer_work_trx = DB::statement("SET @sql = IF(@sql != 's.work_id' ,CONCAT(\"SELECT d.name as DEALER, d.id as dealer_id, \", @sql, \"FROM transactions s JOIN dealers d ON d.id = s.dealer_id WHERE month(s.date) = '". $month ."' and year(s.date) = '". $year ."' and s.deleted_at is null and s.dealer_id = '". $dealer ."' GROUP BY s.dealer_id ORDER BY s.dealer_id ASC\"), CONCAT(\"SELECT d.name as DEALER \", \"FROM transactions s JOIN dealers d ON d.id = s.dealer_id WHERE month(s.date) = '". $month ."' and year(s.date) = '". $year ."' and s.deleted_at is null and s.dealer_id = '". $dealer ."' GROUP BY s.`dealer_id` ORDER BY s.`dealer_id` ASC\"))");
|
if($dealer_datas->count() > 0) {
|
||||||
}else{
|
$allowedDealerIds = $dealer_datas->pluck('id')->toArray();
|
||||||
$dealer_work_trx = DB::statement("SET @sql = IF(@sql != 's.work_id' ,CONCAT(\"SELECT d.name as DEALER, d.id as dealer_id, \", @sql, \"FROM transactions s JOIN dealers d ON d.id = s.dealer_id WHERE month(s.date) = '". $month ."' and year(s.date) = '". $year ."' and s.deleted_at is null GROUP BY s.dealer_id ORDER BY s.dealer_id ASC\"), CONCAT(\"SELECT d.name as DEALER, d.id as dealer_id \", \"FROM transactions s JOIN dealers d ON d.id = s.dealer_id WHERE month(s.date) = '". $month ."' and year(s.date) = '". $year ."' and s.deleted_at is null GROUP BY s.`dealer_id` ORDER BY s.`dealer_id` ASC\"))");
|
if(!in_array($dealer, $allowedDealerIds)) {
|
||||||
|
// If dealer is not allowed, reset to 'all'
|
||||||
|
$dealer = 'all';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// If no dealers are allowed, reset to 'all'
|
||||||
|
$dealer = 'all';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build dealer filter based on user role
|
||||||
|
$dealerFilter = '';
|
||||||
|
if($dealer_datas->count() > 0) {
|
||||||
|
$dealerIds = $dealer_datas->pluck('id')->toArray();
|
||||||
|
$dealerFilter = " and s.dealer_id IN (" . implode(',', $dealerIds) . ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isset($request->dealer) && $request->dealer != 'all') {
|
||||||
|
$dealer_work_trx = DB::statement("SET @sql = IF(@sql != 's.work_id' ,CONCAT(\"SELECT d.name as DEALER, d.id as dealer_id, \", @sql, \"FROM transactions s JOIN dealers d ON d.id = s.dealer_id WHERE month(s.date) = '". $month ."' and year(s.date) = '". $year ."' and s.deleted_at is null and s.dealer_id = '". $dealer ."'". $dealerFilter ." GROUP BY s.dealer_id ORDER BY s.dealer_id ASC\"), CONCAT(\"SELECT d.name as DEALER \", \"FROM transactions s JOIN dealers d ON d.id = s.dealer_id WHERE month(s.date) = '". $month ."' and year(s.date) = '". $year ."' and s.deleted_at is null and s.dealer_id = '". $dealer ."'". $dealerFilter ." GROUP BY s.`dealer_id` ORDER BY s.`dealer_id` ASC\"))");
|
||||||
|
} else {
|
||||||
|
$dealer_work_trx = DB::statement("SET @sql = IF(@sql != 's.work_id' ,CONCAT(\"SELECT d.name as DEALER, d.id as dealer_id, \", @sql, \"FROM transactions s JOIN dealers d ON d.id = s.dealer_id WHERE month(s.date) = '". $month ."' and year(s.date) = '". $year ."' and s.deleted_at is null". $dealerFilter ." GROUP BY s.dealer_id ORDER BY s.dealer_id ASC\"), CONCAT(\"SELECT d.name as DEALER, d.id as dealer_id \", \"FROM transactions s JOIN dealers d ON d.id = s.dealer_id WHERE month(s.date) = '". $month ."' and year(s.date) = '". $year ."' and s.deleted_at is null". $dealerFilter ." GROUP BY s.`dealer_id` ORDER BY s.`dealer_id` ASC\"))");
|
||||||
}
|
}
|
||||||
|
|
||||||
$dealer_work_trx = DB::statement("PREPARE stmt FROM @sql");
|
$dealer_work_trx = DB::statement("PREPARE stmt FROM @sql");
|
||||||
@@ -143,6 +190,11 @@ class AdminController extends Controller
|
|||||||
if(isset($request->dealer) && $request->dealer != 'all') {
|
if(isset($request->dealer) && $request->dealer != 'all') {
|
||||||
$prev_month = $prev_month->where('dealer_id', $request->dealer);
|
$prev_month = $prev_month->where('dealer_id', $request->dealer);
|
||||||
$now_month = $now_month->where('dealer_id', $request->dealer);
|
$now_month = $now_month->where('dealer_id', $request->dealer);
|
||||||
|
} else if($dealer_datas->count() > 0) {
|
||||||
|
// Filter by allowed dealers based on user role
|
||||||
|
$dealerIds = $dealer_datas->pluck('id')->toArray();
|
||||||
|
$prev_month = $prev_month->whereIn('dealer_id', $dealerIds);
|
||||||
|
$now_month = $now_month->whereIn('dealer_id', $dealerIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
$prev_month_trx[] = $prev_month->sum('qty');
|
$prev_month_trx[] = $prev_month->sum('qty');
|
||||||
@@ -160,6 +212,36 @@ class AdminController extends Controller
|
|||||||
return view('dashboard_data', compact('theads', 'work_trx', 'month', 'year', 'dealer_names', 'dealer_trx', 'dealer', 'totals'));
|
return view('dashboard_data', compact('theads', 'work_trx', 'month', 'year', 'dealer_names', 'dealer_trx', 'dealer', 'totals'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if role is admin type
|
||||||
|
*/
|
||||||
|
private function isAdminRole($role)
|
||||||
|
{
|
||||||
|
if (!$role) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define admin role names that should have access to all dealers
|
||||||
|
$adminRoleNames = [
|
||||||
|
'admin'
|
||||||
|
];
|
||||||
|
|
||||||
|
// Check if role name contains admin keywords (but not "area")
|
||||||
|
$roleName = strtolower(trim($role->name));
|
||||||
|
foreach ($adminRoleNames as $adminName) {
|
||||||
|
if (strpos($roleName, $adminName) !== false && strpos($roleName, 'area') === false) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Role with "area" in name should use pivot dealers, not all dealers
|
||||||
|
if (strpos($roleName, 'area') !== false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public function dealer_work_trx(Request $request) {
|
public function dealer_work_trx(Request $request) {
|
||||||
$dealer_work_trx = Work::select(DB::raw('works.name AS work_name'), DB::raw("IFNULL(SUM(t.qty), 0) AS qty"), 'works.id AS work_id')->whereHas('transactions', function($q) use($request) {
|
$dealer_work_trx = Work::select(DB::raw('works.name AS work_name'), DB::raw("IFNULL(SUM(t.qty), 0) AS qty"), 'works.id AS work_id')->whereHas('transactions', function($q) use($request) {
|
||||||
if(isset($request->month)) {
|
if(isset($request->month)) {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ use Illuminate\Support\Facades\DB;
|
|||||||
use Illuminate\Support\Facades\Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Yajra\DataTables\Facades\DataTables;
|
use Yajra\DataTables\Facades\DataTables;
|
||||||
use Maatwebsite\Excel\Facades\Excel;
|
use Maatwebsite\Excel\Facades\Excel;
|
||||||
|
use App\Models\Role;
|
||||||
|
|
||||||
class ReportController extends Controller
|
class ReportController extends Controller
|
||||||
{
|
{
|
||||||
@@ -383,10 +384,20 @@ class ReportController extends Controller
|
|||||||
$request['year'] = date('Y');
|
$request['year'] = date('Y');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$user = Auth::user();
|
||||||
|
$role = Role::with(['dealers' => function($query) {
|
||||||
|
$query->whereNull('dealers.deleted_at'); // Only active dealers
|
||||||
|
}])->find($user->role_id);
|
||||||
|
|
||||||
|
if(strtolower($role->name) === 'admin') {
|
||||||
|
$dealer_datas = Dealer::all();
|
||||||
|
}else{
|
||||||
|
$dealer_datas = $role->dealers()->whereNull('dealers.deleted_at')->orderBy('name')->get();
|
||||||
|
}
|
||||||
|
|
||||||
$year = $request->year;
|
$year = $request->year;
|
||||||
$month = $request->month;
|
$month = $request->month;
|
||||||
$dealer = $request->dealer;
|
$dealer = $request->dealer;
|
||||||
$dealer_datas = Dealer::all();
|
|
||||||
$ajax_url = route('dashboard_data').'?month='.$month.'&year='.$year.'&dealer='.$dealer;
|
$ajax_url = route('dashboard_data').'?month='.$month.'&year='.$year.'&dealer='.$dealer;
|
||||||
return view('dashboard', compact('month', 'ajax_url', 'dealer', 'dealer_datas', 'year'));
|
return view('dashboard', compact('month', 'ajax_url', 'dealer', 'dealer_datas', 'year'));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,8 @@ class ReportStockProductsController extends Controller
|
|||||||
|
|
||||||
public function getDealers()
|
public function getDealers()
|
||||||
{
|
{
|
||||||
$dealers = Dealer::orderBy('name')->get(['id', 'name', 'dealer_code']);
|
$stockService = new StockReportService();
|
||||||
|
$dealers = $stockService->getDealersBasedOnUserRole();
|
||||||
return response()->json($dealers);
|
return response()->json($dealers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,9 +6,12 @@ use App\Models\Product;
|
|||||||
use App\Models\Dealer;
|
use App\Models\Dealer;
|
||||||
use App\Models\Stock;
|
use App\Models\Stock;
|
||||||
use App\Models\StockLog;
|
use App\Models\StockLog;
|
||||||
|
use App\Models\Role;
|
||||||
|
use App\Models\User;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
class StockReportService
|
class StockReportService
|
||||||
{
|
{
|
||||||
@@ -19,8 +22,8 @@ class StockReportService
|
|||||||
{
|
{
|
||||||
$targetDate = $targetDate ? Carbon::parse($targetDate) : now();
|
$targetDate = $targetDate ? Carbon::parse($targetDate) : now();
|
||||||
|
|
||||||
// Get all dealers
|
// Get dealers based on user role
|
||||||
$dealers = Dealer::orderBy('name')->get();
|
$dealers = $this->getDealersBasedOnUserRole();
|
||||||
|
|
||||||
// Get all active products
|
// Get all active products
|
||||||
$products = Product::where('active', true)
|
$products = Product::where('active', true)
|
||||||
@@ -98,8 +101,8 @@ class StockReportService
|
|||||||
{
|
{
|
||||||
$targetDate = $targetDate ? Carbon::parse($targetDate) : now();
|
$targetDate = $targetDate ? Carbon::parse($targetDate) : now();
|
||||||
|
|
||||||
// Get all dealers
|
// Get dealers based on user role
|
||||||
$dealers = Dealer::orderBy('name')->get();
|
$dealers = $this->getDealersBasedOnUserRole();
|
||||||
|
|
||||||
// Get all active products with their stock data
|
// Get all active products with their stock data
|
||||||
$products = Product::where('active', true)
|
$products = Product::where('active', true)
|
||||||
@@ -135,6 +138,117 @@ class StockReportService
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get dealers based on logged-in user's role
|
||||||
|
*/
|
||||||
|
public function getDealersBasedOnUserRole()
|
||||||
|
{
|
||||||
|
// Get current authenticated user
|
||||||
|
$user = Auth::user();
|
||||||
|
|
||||||
|
if (!$user) {
|
||||||
|
Log::warning('No authenticated user found, returning all dealers');
|
||||||
|
return Dealer::whereNull('deleted_at')->orderBy('name')->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::info('Getting dealers for user:', [
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'user_role_id' => $user->role_id,
|
||||||
|
'user_dealer_id' => $user->dealer_id
|
||||||
|
]);
|
||||||
|
|
||||||
|
// If user has role, check role type and dealer access
|
||||||
|
if ($user->role_id) {
|
||||||
|
$role = Role::with(['dealers' => function($query) {
|
||||||
|
$query->whereNull('dealers.deleted_at'); // Only active dealers
|
||||||
|
}])->find($user->role_id);
|
||||||
|
|
||||||
|
if ($role) {
|
||||||
|
// Check if role is admin type
|
||||||
|
if ($this->isAdminRole($role)) {
|
||||||
|
// Admin role - check if has pivot dealers
|
||||||
|
if ($role->dealers->count() > 0) {
|
||||||
|
// Admin with pivot dealers - return pivot dealers only
|
||||||
|
Log::info('Admin role with pivot dealers, returning pivot dealers only');
|
||||||
|
$dealers = $role->dealers()->whereNull('dealers.deleted_at')->orderBy('name')->get();
|
||||||
|
Log::info('Returning pivot dealers for admin:', $dealers->pluck('name')->toArray());
|
||||||
|
return $dealers;
|
||||||
|
} else {
|
||||||
|
// Admin without pivot dealers - return all dealers
|
||||||
|
Log::info('Admin role without pivot dealers, returning all dealers');
|
||||||
|
$allDealers = Dealer::whereNull('deleted_at')->orderBy('name')->get();
|
||||||
|
Log::info('Returning all dealers for admin:', $allDealers->pluck('name')->toArray());
|
||||||
|
return $allDealers;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non-admin role - return dealers from role pivot
|
||||||
|
if ($role->dealers->count() > 0) {
|
||||||
|
Log::info('Non-admin role with dealers, returning role dealers');
|
||||||
|
$dealers = $role->dealers()->whereNull('dealers.deleted_at')->orderBy('name')->get();
|
||||||
|
Log::info('Returning dealers from role:', $dealers->pluck('name')->toArray());
|
||||||
|
return $dealers;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If user has specific dealer_id but no role dealers, check if they can access their dealer_id
|
||||||
|
if ($user->dealer_id) {
|
||||||
|
Log::info('User has specific dealer_id:', ['dealer_id' => $user->dealer_id]);
|
||||||
|
if ($user->role_id) {
|
||||||
|
$role = Role::with(['dealers' => function($query) {
|
||||||
|
$query->whereNull('dealers.deleted_at'); // Only active dealers
|
||||||
|
}])->find($user->role_id);
|
||||||
|
|
||||||
|
if ($role && $role->hasDealer($user->dealer_id)) {
|
||||||
|
Log::info('User can access their dealer_id, returning single dealer');
|
||||||
|
$dealer = Dealer::where('id', $user->dealer_id)->whereNull('deleted_at')->orderBy('name')->get();
|
||||||
|
Log::info('Returning dealer:', $dealer->pluck('name')->toArray());
|
||||||
|
return $dealer;
|
||||||
|
} else {
|
||||||
|
Log::info('User cannot access their dealer_id');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Log::info('User has dealer_id but no role or no access, returning empty');
|
||||||
|
return collect();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback: return all dealers if no restrictions
|
||||||
|
Log::info('No restrictions found, returning all dealers');
|
||||||
|
$allDealers = Dealer::whereNull('deleted_at')->orderBy('name')->get();
|
||||||
|
Log::info('Returning all dealers:', $allDealers->pluck('name')->toArray());
|
||||||
|
return $allDealers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if role is admin type (should show all dealers if no pivot)
|
||||||
|
*/
|
||||||
|
private function isAdminRole($role)
|
||||||
|
{
|
||||||
|
// Define admin role names that should have access to all dealers
|
||||||
|
$adminRoleNames = [
|
||||||
|
'admin'
|
||||||
|
];
|
||||||
|
|
||||||
|
// Check if role name contains admin keywords (but not "area")
|
||||||
|
$roleName = strtolower(trim($role->name));
|
||||||
|
foreach ($adminRoleNames as $adminName) {
|
||||||
|
if (strpos($roleName, $adminName) !== false && strpos($roleName, 'area') === false) {
|
||||||
|
Log::info('Role identified as admin type:', ['role_name' => $role->name]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Role with "area" in name should use pivot dealers, not all dealers
|
||||||
|
if (strpos($roleName, 'area') !== false) {
|
||||||
|
Log::info('Role contains "area", treating as area role (use pivot dealers):', ['role_name' => $role->name]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::info('Role is not admin type:', ['role_name' => $role->name]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optimized method to get stock on date using subquery
|
* Optimized method to get stock on date using subquery
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -450,11 +450,7 @@ class TechnicianReportService
|
|||||||
{
|
{
|
||||||
// Define admin role names that should have access to all dealers
|
// Define admin role names that should have access to all dealers
|
||||||
$adminRoleNames = [
|
$adminRoleNames = [
|
||||||
'admin',
|
'admin'
|
||||||
'super admin',
|
|
||||||
'administrator',
|
|
||||||
'sa',
|
|
||||||
'superadmin'
|
|
||||||
];
|
];
|
||||||
|
|
||||||
// Check if role name contains admin keywords (but not "area")
|
// Check if role name contains admin keywords (but not "area")
|
||||||
|
|||||||
Reference in New Issue
Block a user