Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions app/Http/Controllers/DashboardController.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,22 @@ public function index(Request $request)
$queryBase = Visitor::query()
->whereHas('voucher');

if ($user->department_id !== 1) {
if (!$user->isAdmin()) {
$queryBase->whereHas('creator', fn ($q) =>
$q->where('department_id', $user->department_id)
);
}

$totalVisitors = (clone $queryBase)->count();

$voucherQuery = Voucher::query();
if (!$user->isAdmin()) {
$voucherQuery->whereHas('visitor.creator', fn ($q) =>
$q->where('department_id', $user->department_id)
);
}
$totalVouchers = $voucherQuery->count();

$totalThisMonth = (clone $queryBase)
->whereBetween('created_at', [
$today->copy()->startOfMonth(),
Expand All @@ -42,7 +50,7 @@ public function index(Request $request)
->count();

$departments = Department::all();
if ($user->department_id !== 1) {
if (!$user->isAdmin()) {
$departments = $departments->where('id', $user->department_id);
}

Expand Down Expand Up @@ -83,7 +91,7 @@ public function index(Request $request)
->where('expires_at', '>=', $today->startOfDay())
->where('expires_at', '<', $today->copy()->addDays(8));

if ($user->department_id !== 1) {
if (!$user->isAdmin()) {
$nextToExpireQuery->whereHas('visitor.creator', fn ($q) =>
$q->where('department_id', $user->department_id)
);
Expand All @@ -101,7 +109,7 @@ public function index(Request $request)
->where('expires_at', '<', $today)
->whereHas('voucher');

if ($user->department_id !== 1) {
if (!$user->isAdmin()) {
$alreadyExpiredQuery->whereHas('creator', fn ($q) =>
$q->where('department_id', $user->department_id)
);
Expand Down Expand Up @@ -165,7 +173,7 @@ public function index(Request $request)

$importStatsQuery = ImportBatch::query();

if ($user->department_id !== 1) {
if (!$user->isAdmin()) {
$importStatsQuery->where('created_by', $user->id);
}

Expand All @@ -178,7 +186,7 @@ public function index(Request $request)

$recentImportsQuery = ImportBatch::with('creator:id,name');

if ($user->department_id !== 1) {
if (!$user->isAdmin()) {
$recentImportsQuery->where('created_by', $user->id);
}

Expand All @@ -200,6 +208,7 @@ public function index(Request $request)
return Inertia::render('dashboard', [
'stats' => [
'totalVisitors' => $totalVisitors,
'totalVouchers' => $totalVouchers,
'totalThisMonth' => $totalThisMonth,
'expiredVisitors' => $expiredVisitors,
],
Expand Down
15 changes: 8 additions & 7 deletions app/Http/Controllers/UsersController.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ public function index(UserIndexRequest $request)
{
$filters = $request->validated();

$user = auth()->user();

$query = User::with('department')
->search($filters['search'] ?? null)
->departmentFilter($filters['department_id'] ?? null)
->departmentFilter($filters['department_id'] ?? null, $user)
->applyOrdering(
$filters['order_name'] ?? null,
$filters['order_created'] ?? null,
Expand Down Expand Up @@ -56,14 +58,13 @@ public function edit(User $user)
public function update(Request $request, User $user)
{
$request->validate([
'role' => ['required', 'in:admin,operator'],
'enabled' => ['required', 'boolean'],
'active' => ['required', 'in:0,1'],
]);

$user->update([
'role' => $request->role,
'enabled' => $request->enabled,
]);
$user->load('department');
$user->syncRoleFromDepartment();
$user->enabled = $request->active === '1';
$user->save();

return redirect()->route('users.index');
}
Expand Down
9 changes: 6 additions & 3 deletions app/Http/Controllers/VisitorTypeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ public function store(Request $request, ActivityLogInterface $activityLogService
auth()->id()
);

return redirect()->route('visitorTypes.index');
return redirect()->route('visitorTypes.index')
->with('success', 'Tipo de visitante criado com sucesso.');
}

public function edit(VisitorType $visitorType)
Expand All @@ -80,7 +81,8 @@ public function update(Request $request, VisitorType $visitorType)

$visitorType->update($request->only(['name', 'description']));

return redirect()->route('visitorTypes.index');
return redirect()->route('visitorTypes.index')
->with('success', 'Tipo de visitante atualizado com sucesso.');
}

public function destroy(VisitorType $visitorType, ActivityLogInterface $activityLogService)
Expand All @@ -94,6 +96,7 @@ public function destroy(VisitorType $visitorType, ActivityLogInterface $activity
auth()->id()
);

return redirect()->route('visitorTypes.index');
return redirect()->route('visitorTypes.index')
->with('success', 'Tipo de visitante excluído com sucesso.');
}
}
1 change: 1 addition & 0 deletions app/Http/Controllers/VisitorsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ public function index(VisitorIndexRequest $request)
'filters' => $filters,
'types' => VisitorType::select(['id', 'name'])->get(),
'user_department_id' => $user->department_id,
'is_admin' => $user->isAdmin(),
'departments' => Department::select(['id', 'name'])->get(),
]);
}
Expand Down
1 change: 1 addition & 0 deletions app/Http/Controllers/VouchersController.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public function index(VoucherIndexRequest $request)
'creators' => User::select(['id', 'name'])->get(),
'departments' => Department::select(['id', 'name'])->get(),
'user_department_id' => $user->department_id,
'is_admin' => $user->isAdmin(),
]);

}
Expand Down
2 changes: 1 addition & 1 deletion app/Http/Requests/UserIndexRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public function rules(): array
{
return [
'search' => ['nullable', 'string', 'max:255'],
'type_id' => ['nullable', 'integer', 'exists:visitor_types,id'],
'department_id' => ['nullable', 'integer', 'exists:departments,id'],
'order_name' => ['nullable', 'in:asc,desc'],
'order_created' => ['nullable', 'in:newest,oldest'],
'order_department' => ['nullable', 'integer'],
Expand Down
1 change: 1 addition & 0 deletions app/Http/Requests/VisitorIndexRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public function rules(): array
'search' => ['nullable', 'string', 'max:255'],
'type_id' => ['nullable', 'integer', 'exists:visitor_types,id'],
'department_id' => ['nullable', 'integer', 'exists:departments,id'],
'order_department' => ['nullable', 'integer', 'exists:departments,id'],
'order_name' => ['nullable', 'in:asc,desc'],
'order_created' => ['nullable', 'in:newest,oldest'],
'sort' => ['nullable', 'in:id,name,created_at'],
Expand Down
2 changes: 1 addition & 1 deletion app/Http/Requests/VoucherIndexRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public function rules(): array
'search' => ['nullable', 'string', 'max:255'],
'type_id' => ['nullable', 'integer', 'exists:visitor_types,id'],
'creator_id' => ['nullable', 'integer', 'exists:users,id'],
'order_department' => ['nullable'],
'order_department' => ['nullable', 'integer', 'exists:departments,id'],
'expire_sort' => ['nullable', 'in:closest,furthest'],
'created_sort' => ['nullable', 'in:newest,oldest'],
'sort' => ['nullable', 'string', 'in:id,created_at,expires_at,login'],
Expand Down
11 changes: 10 additions & 1 deletion app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ public function belongsToDepartment(Department $department): bool
return $this->department_id === $department->id;
}

public function syncRoleFromDepartment(): void
{
$this->role = $this->department?->name === 'COGETI' ? 'admin' : 'operator';
}

/**
* Verifica se é admin pelo papel vindo do AD
*/
Expand Down Expand Up @@ -94,8 +99,12 @@ public function scopeSearch(Builder $query, ?string $search): Builder
});
}

public function scopeDepartmentFilter(Builder $query, ?int $departmentId): Builder
public function scopeDepartmentFilter(Builder $query, ?int $departmentId, ?User $authUser = null): Builder
{
if ($authUser && !$authUser->isAdmin()) {
return $query->where('department_id', $authUser->department_id);
}

if (!$departmentId) {
return $query;
}
Expand Down
3 changes: 1 addition & 2 deletions app/Models/Voucher.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@ public function scopeDepartmentFilter(
User $user,
?int $departmentId
): Builder {
// COGETI
if ($user->department_id === 1) {
if ($user->isAdmin()) {
if ($departmentId && $departmentId !== 'all') {
return $query->whereHas(
'visitor.creator',
Expand Down
5 changes: 4 additions & 1 deletion app/Services/SambaService.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ class SambaService implements SambaInterface
protected string $keyPath;
protected int $port;
protected bool $debug = true;
protected int $timeout = 10;
protected int $connectionTimeout = 5;

public function __construct()
{
Expand All @@ -25,7 +27,8 @@ public function __construct()

protected function connect(): SSH2
{
$ssh = new SSH2($this->host, $this->port);
$ssh = new SSH2($this->host, $this->port, $this->connectionTimeout);
$ssh->setTimeout($this->timeout);

$key = PublicKeyLoader::loadPrivateKey(
file_get_contents($this->keyPath)
Expand Down
2 changes: 1 addition & 1 deletion app/Services/VisitorService.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ public function delete(Visitor $visitor, int $userId): void
if (!$result['success']) {
$errorMsg = $result['error'] ?? 'Erro desconhecido';

if (stripos($errorMsg, 'NT_STATUS_NO_SUCH_USER') !== false || stripos($errorMsg, 'not found') !== false) {
if (stripos($errorMsg, 'NT_STATUS_NO_SUCH_USER') !== false || stripos($errorMsg, 'not found') !== false || stripos($errorMsg, 'Unable to find user') !== false) {
\Log::warning('Usuário SAMBA não encontrado, continuando remoção local', ['login' => $login]);
} else {
\Log::error('Erro ao deletar usuário SAMBA', [
Expand Down
8 changes: 4 additions & 4 deletions resources/js/components/visitors/visitors-filters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ interface VisitorsFiltersProps {
types: Array<{ id: number; name: string }>;
onChange: (filters: Record<string, unknown>) => void;
onClear: () => void;
userDepartmentId: number;
isAdmin: boolean;
departments: Array<{ id: number; name: string }>;
}

Expand All @@ -22,7 +22,7 @@ export default function VisitorsFilters({
types,
onChange,
onClear,
userDepartmentId,
isAdmin,
departments,
}: VisitorsFiltersProps) {
const [typeId, setTypeId] = useState(filters?.type_id ?? "all");
Expand All @@ -49,7 +49,7 @@ export default function VisitorsFilters({
params.order_created = orderCreated;
}

if (userDepartmentId === 1 && orderDepartment !== "none") {
if (isAdmin && orderDepartment !== "none") {
params.order_department = orderDepartment;
}

Expand Down Expand Up @@ -116,7 +116,7 @@ export default function VisitorsFilters({
</div>

{/* DEPARTAMENTO */}
{userDepartmentId === 1 && (
{isAdmin && (
<div className="flex flex-col gap-2">
<label className="font-medium text-sm">Departamento</label>
<Select
Expand Down
8 changes: 4 additions & 4 deletions resources/js/components/vouchers/vouchers-filters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ interface VouchersFiltersProps {
creators: Array<{ id: number; name: string }>;
onChange: (filters: Record<string, unknown>) => void;
onClear: () => void;
userDepartmentId: number;
isAdmin: boolean;
departments: Array<{ id: number; name: string }>;
}

Expand All @@ -22,7 +22,7 @@ export default function VouchersFilters({
creators,
onChange,
onClear,
userDepartmentId,
isAdmin,
departments,
}: VouchersFiltersProps) {
const [creatorId, setCreatorId] = useState(filters?.creator_id ?? "all");
Expand All @@ -38,7 +38,7 @@ export default function VouchersFilters({
if (creatorId !== "all") params.creator_id = creatorId;
if (orderExpire !== "none") params.expire_sort = orderExpire;
if (orderCreated !== "none") params.created_sort = orderCreated;
if (userDepartmentId === 1 && orderDepartment !== "none") {
if (isAdmin && orderDepartment !== "none") {
params.order_department = orderDepartment;
}

Expand Down Expand Up @@ -104,7 +104,7 @@ export default function VouchersFilters({
</div>

{/* DEPARTAMENTO */}
{userDepartmentId === 1 && (
{isAdmin && (
<div className="flex flex-col gap-2">
<label className="font-medium text-sm">Departamento</label>
<Select value={orderDepartment} onValueChange={setOrderDepartment}>
Expand Down
3 changes: 2 additions & 1 deletion resources/js/layouts/app-layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ interface PageProps {
}

export default function AppLayout({ children, breadcrumbs, ...props }: AppLayoutProps) {
const { flash, errors } = usePage<PageProps>()
const { props: pageProps } = usePage<PageProps>();
const { flash, errors } = pageProps

useEffect(() => {
if (flash?.success) {
Expand Down
17 changes: 16 additions & 1 deletion resources/js/pages/dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { dashboard } from '@/routes';
import { type BreadcrumbItem } from '@/types';
import { usePage, router, Link } from '@inertiajs/react';
import { shortenName } from '@/lib/utils';
import { Users, Calendar, Clock, AlertCircle, FileSpreadsheet, CheckCircle, XCircle } from 'lucide-react';
import { Users, Calendar, Clock, AlertCircle, FileSpreadsheet, CheckCircle, XCircle, Receipt } from 'lucide-react';
import { useEffect } from 'react';

const breadcrumbs: BreadcrumbItem[] = [
Expand All @@ -17,6 +17,7 @@ const breadcrumbs: BreadcrumbItem[] = [

interface DashboardStats {
totalVisitors: number;
totalVouchers: number;
totalThisMonth: number;
expiredVisitors: number;
}
Expand Down Expand Up @@ -130,6 +131,20 @@ export default function Dashboard() {
</CardContent>
</Card>

<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">
Total de Vouchers
</CardTitle>
<Receipt className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">
{stats.totalVouchers}
</div>
</CardContent>
</Card>

<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">
Expand Down
21 changes: 0 additions & 21 deletions resources/js/pages/users/create.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ export default function CreateUser({ departments }: { departments: Array<{ id: n
name: '',
email: '',
password: '',
role: 'operator', // default
department_id: departments.length ? String(departments[0].id) : '',
});

Expand Down Expand Up @@ -90,26 +89,6 @@ export default function CreateUser({ departments }: { departments: Array<{ id: n
)}
</div>

{/* Role */}
<div>
<Label htmlFor="role">Função</Label>
<Select
value={data.role}
onValueChange={(value) => setData('role', value)}
>
<SelectTrigger className="w-full">
<SelectValue placeholder="Selecione o papel" />
</SelectTrigger>
<SelectContent>
<SelectItem value="admin">Administrador</SelectItem>
<SelectItem value="operator">Operador</SelectItem>
</SelectContent>
</Select>
{errors.role && (
<p className="mt-1 text-sm text-red-500">{errors.role}</p>
)}
</div>

{/* Departamento */}
<div>
<Label htmlFor="department_id">Departamento</Label>
Expand Down
Loading
Loading