big update base struktur tahap 1

This commit is contained in:
Wian Drs
2026-07-27 16:24:09 +07:00
parent 2b3592c4c2
commit 1dd02baa72
169 changed files with 24405 additions and 977 deletions
@@ -0,0 +1,146 @@
<?php
namespace App\Http\Controllers\Menu;
use App\Http\Controllers\ApiController;
use App\Models\MenuList;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
class MenuController extends ApiController
{
public function myMenus()
{
$user = auth()->user();
$tenantId = request()->attributes->get('tenant_id');
if (! $user) {
return $this->error('Unauthenticated', 401);
}
if ($user->isMasterAdmin()) {
$menus = MenuList::query()
->where('is_active', true)
->orderBy('sort_order')
->orderBy('id')
->get()
->map(function (MenuList $menu) {
return [
'id' => $menu->id,
'parent_id' => $menu->parent_id,
'name' => $menu->name,
'slug' => $menu->slug,
'url' => $menu->url,
'icon' => $menu->icon,
'component' => $menu->component,
'sort_order' => $menu->sort_order,
'permissions' => [
'can_view' => true,
'can_create' => true,
'can_update' => true,
'can_delete' => true,
'can_approve' => true,
'can_export' => true,
],
];
});
} else {
$menuRows = DB::table('menu_lists as m')
->join('menu_group_menus as mgm', 'mgm.menu_id', '=', 'm.id')
->join('user_menu_groups as umg', 'umg.menu_group_id', '=', 'mgm.menu_group_id')
->join('menu_groups as mg', 'mg.id', '=', 'umg.menu_group_id')
->where('umg.user_id', $user->id)
->where('umg.tenant_id', $tenantId)
->where('mg.is_active', true)
->where('m.is_active', true)
->where('mgm.can_view', true)
->groupBy(
'm.id',
'm.parent_id',
'm.name',
'm.slug',
'm.url',
'm.icon',
'm.component',
'm.sort_order'
)
->select(
'm.id',
'm.parent_id',
'm.name',
'm.slug',
'm.url',
'm.icon',
'm.component',
'm.sort_order',
DB::raw('MAX(CASE WHEN mgm.can_view THEN 1 ELSE 0 END) as can_view'),
DB::raw('MAX(CASE WHEN mgm.can_create THEN 1 ELSE 0 END) as can_create'),
DB::raw('MAX(CASE WHEN mgm.can_update THEN 1 ELSE 0 END) as can_update'),
DB::raw('MAX(CASE WHEN mgm.can_delete THEN 1 ELSE 0 END) as can_delete'),
DB::raw('MAX(CASE WHEN mgm.can_approve THEN 1 ELSE 0 END) as can_approve'),
DB::raw('MAX(CASE WHEN mgm.can_export THEN 1 ELSE 0 END) as can_export')
)
->orderBy('m.sort_order')
->orderBy('m.id')
->get();
$menus = $menuRows->map(function ($row) {
return [
'id' => (int) $row->id,
'parent_id' => $row->parent_id ? (int) $row->parent_id : null,
'name' => $row->name,
'slug' => $row->slug,
'url' => $row->url,
'icon' => $row->icon,
'component' => $row->component,
'sort_order' => (int) $row->sort_order,
'permissions' => [
'can_view' => (bool) $row->can_view,
'can_create' => (bool) $row->can_create,
'can_update' => (bool) $row->can_update,
'can_delete' => (bool) $row->can_delete,
'can_approve' => (bool) $row->can_approve,
'can_export' => (bool) $row->can_export,
],
];
});
}
$tree = $this->buildMenuTree($menus);
return $this->success(
[
'is_master' => (bool) $user->is_master,
'access_level' => $user->access_level->value,
'tenant_id' => $tenantId,
'menus' => $tree,
],
'Menu berhasil diambil'
);
}
private function buildMenuTree(Collection $menus, ?int $parentId = null): array
{
return $menus
->filter(fn ($menu) => $menu['parent_id'] === $parentId)
->sortBy('sort_order')
->values()
->map(function ($menu) use ($menus) {
$children = $this->buildMenuTree($menus, $menu['id']);
return [
'id' => $menu['id'],
'parent_id' => $menu['parent_id'],
'name' => $menu['name'],
'slug' => $menu['slug'],
'url' => $menu['url'],
'icon' => $menu['icon'],
'component' => $menu['component'],
'sort_order' => $menu['sort_order'],
'permissions' => $menu['permissions'],
'children' => $children,
];
})
->all();
}
}
@@ -0,0 +1,206 @@
<?php
namespace App\Http\Controllers\Menu;
use App\Http\Controllers\ApiController;
use App\Http\Requests\MenuGroup\IndexMenuGroupRequest;
use App\Http\Requests\MenuGroup\StoreMenuGroupRequest;
use App\Http\Requests\MenuGroup\SyncMenuGroupMenusRequest;
use App\Http\Requests\MenuGroup\SyncUserMenuGroupsRequest;
use App\Http\Requests\MenuGroup\UpdateMenuGroupRequest;
use App\Http\Resources\MenuGroup\MenuGroupResource;
use App\Models\MenuGroup;
use App\Models\User;
use App\Services\Access\AccessService;
use App\Services\Menu\MenuGroupService;
class MenuGroupController extends ApiController
{
public function __construct(
protected MenuGroupService $service,
protected AccessService $access
) {}
public function index(IndexMenuGroupRequest $request)
{
$data = $this->service->list(
$request->validated(),
$request->user(),
$request->attributes->get('tenant_id')
);
return $this->successPaginated(
$data,
MenuGroupResource::class,
'Data Menu Group berhasil diambil'
);
}
public function store(StoreMenuGroupRequest $request)
{
$data = $this->service->create(
$request->validated(),
$request->user(),
$request->attributes->get('tenant_id')
);
return $this->created(
new MenuGroupResource($data),
'Menu Group berhasil dibuat'
);
}
public function show(MenuGroup $menu_group)
{
$this->authorizeGroup($menu_group, false);
return $this->success(
new MenuGroupResource($menu_group->load('tenant')),
'Detail Menu Group berhasil diambil'
);
}
public function update(
UpdateMenuGroupRequest $request,
MenuGroup $menu_group
) {
$this->authorizeGroup($menu_group, true);
$data = $this->service->update(
$menu_group,
$request->validated(),
$request->user(),
$request->attributes->get('tenant_id')
);
return $this->updated(
new MenuGroupResource($data),
'Menu Group berhasil diupdate'
);
}
public function destroy(MenuGroup $menu_group)
{
$this->authorizeGroup($menu_group, true);
$this->service->delete($menu_group);
return $this->deleted(
'Menu Group berhasil dihapus'
);
}
public function menus(MenuGroup $menu_group)
{
$this->authorizeGroup($menu_group, false);
$data = $this->service->listMenus($menu_group);
return $this->success(
[
'menu_group_id' => $menu_group->id,
'menu_group' => new MenuGroupResource($menu_group),
'menus' => $data,
],
'Mapping menu group berhasil diambil'
);
}
public function availableMenus(MenuGroup $menu_group)
{
$this->authorizeGroup($menu_group, false);
$user = auth()->user();
if (! $user) {
return $this->error('Unauthenticated', 401);
}
$data = $this->service->listAvailableMenusForGroup(
$menu_group,
$user
);
return $this->success(
[
'menu_group_id' => $menu_group->id,
'menu_group' => new MenuGroupResource($menu_group),
'menus' => $data,
],
'Daftar menu tersedia berdasarkan akses user berhasil diambil'
);
}
public function syncMenus(
SyncMenuGroupMenusRequest $request,
MenuGroup $menu_group
) {
$this->authorizeGroup($menu_group, true);
$user = auth()->user();
if (! $user) {
return $this->error('Unauthenticated', 401);
}
$this->service->syncMenus(
$menu_group,
$request->validated('menus'),
$user
);
return $this->success(
[
'menu_group_id' => $menu_group->id,
'menu_group' => new MenuGroupResource($menu_group->fresh('tenant')),
'menus' => $this->service->listMenus($menu_group),
],
'Mapping menu group berhasil disimpan'
);
}
public function userAssignments(User $user)
{
$tenantId = request()->attributes->get('tenant_id');
abort_unless($this->access->canManageUser(auth()->user(), $user, $tenantId), 403);
return $this->success(
[
'user_id' => $user->id,
'assignments' => $this->service->listUserAssignments($user, $tenantId),
],
'Assignment user menu group berhasil diambil'
);
}
public function syncUserAssignments(
SyncUserMenuGroupsRequest $request,
User $user
) {
$tenantId = $request->attributes->get('tenant_id');
abort_unless($this->access->canManageUser($request->user(), $user, $tenantId), 403);
$this->service->syncUserAssignments(
$user,
$request->validated('assignments'),
$tenantId
);
return $this->success(
[
'user_id' => $user->id,
'assignments' => $this->service->listUserAssignments($user, $tenantId),
],
'Assignment user menu group berhasil disimpan'
);
}
private function authorizeGroup(MenuGroup $menuGroup, bool $write): void
{
$user = auth()->user();
$tenantId = request()->attributes->get('tenant_id');
if ($user->isMasterAdmin()) {
return;
}
$allowed = (int) $menuGroup->tenant_id === (int) $tenantId;
abort_unless($allowed, 403);
}
}
@@ -0,0 +1,75 @@
<?php
namespace App\Http\Controllers\Menu;
use App\Http\Controllers\ApiController;
use App\Http\Requests\MenuList\IndexMenuListRequest;
use App\Http\Requests\MenuList\StoreMenuListRequest;
use App\Http\Requests\MenuList\UpdateMenuListRequest;
use App\Http\Resources\MenuList\MenuListResource;
use App\Models\MenuList;
use App\Services\Menu\MenuListService;
class MenuListController extends ApiController
{
public function __construct(
protected MenuListService $service
) {}
public function index(IndexMenuListRequest $request)
{
$data = $this->service->list(
$request->validated()
);
return $this->successPaginated(
$data,
MenuListResource::class,
'Data Menu List berhasil diambil'
);
}
public function store(StoreMenuListRequest $request)
{
$data = $this->service->create(
$request->validated()
);
return $this->created(
new MenuListResource($data),
'Menu List berhasil dibuat'
);
}
public function show(MenuList $menu_list)
{
return $this->success(
new MenuListResource($menu_list),
'Detail Menu List berhasil diambil'
);
}
public function update(
UpdateMenuListRequest $request,
MenuList $menu_list
) {
$data = $this->service->update(
$menu_list,
$request->validated()
);
return $this->updated(
new MenuListResource($data),
'Menu List berhasil diupdate'
);
}
public function destroy(MenuList $menu_list)
{
$this->service->delete($menu_list);
return $this->deleted(
'Menu List berhasil dihapus'
);
}
}