Merge branch 'branch-jagad' into 'main'

add budgets

See merge request fiqhpratama1/xpendify!17
This commit is contained in:
Jagad Raya
2025-01-07 10:24:37 +00:00
24 changed files with 868 additions and 36 deletions
@@ -0,0 +1,153 @@
<?php
declare(strict_types=1);
namespace App\Http\Controllers\Backend;
use App\Http\Controllers\Controller;
use App\Models\BudgetControl;
use App\Models\BudgetControlLog;
use App\Models\Admin;
use Illuminate\Http\Request;
use App\Models\FormUpCountry;
use App\Models\FormMeetingSeminar;
use App\Models\FormOthers;
use App\Models\FormEntertaimentPresentation;
use App\Models\FormVehicleRunningCost;
class BudgetControlController extends Controller
{
public function index()
{
$this->checkAuthorization(auth()->user(), ['budget_control.view']);
session()->put('redirect_url', route('budget_control'));
// Get the budget control data
$budget = BudgetControl::orderBy('created_at', 'desc')->with(['user', 'cabang'])->get();
// Initialize an empty array to hold the used budget sums
$usedBudget = [];
foreach ($budget as $b) {
// Get the month and year from the budget
$month = $b->periode_month;
$year = $b->periode_year;
// Add the used budget per model for the specified month and year to the usedBudget array
$usedBudget[] = [
'FormUpCountry' => FormUpCountry::whereIn('status', ['Approved', 'Closed'])
->whereMonth('tanggal', '=', date('m', strtotime($month)))
->whereYear('tanggal', '=', $year)
->sum('approved_total'),
'FormMeetingSeminar' => FormMeetingSeminar::whereIn('status', ['Approved', 'Closed'])
->whereMonth('created_at', '=', date('m', strtotime($month)))
->whereYear('created_at', '=', $year)
->sum('approved_total'),
'FormOthers' => FormOthers::whereIn('status', ['Approved', 'Closed'])
->whereMonth('tanggal', '=', date('m', strtotime($month)))
->whereYear('tanggal', '=', $year)
->sum('approved_total'),
'FormEntertaimentPresentation' => FormEntertaimentPresentation::whereIn('status', ['Approved', 'Closed'])
->whereMonth('tanggal', '=', date('m', strtotime($month)))
->whereYear('tanggal', '=', $year)
->sum('approved_total'),
'FormVehicleRunningCost' => FormVehicleRunningCost::whereIn('status', ['Approved', 'Closed'])
->whereMonth('tanggal', '=', date('m', strtotime($month)))
->whereYear('tanggal', '=', $year)
->sum('approved_total')
];
}
$usedBudget = array_sum(array_map(function ($b) {
return array_sum($b);
}, $usedBudget));
return view(
'backend.pages.budget_control.index',
[
'data' => $budget,
'usedBudget' => $usedBudget,
'availableBudget' => $budget->sum('amount') - $usedBudget,
]
);
}
public function log()
{
$this->checkAuthorization(auth()->user(), ['budget_control.view']);
session()->put('redirect_url', route('budget_control'));
return view(
'backend.pages.budget_control.log',
[
'data' => BudgetControlLog::orderBy('created_at', 'desc')->with(['user', 'cabang'])->get(),
]
);
}
public function create()
{
$this->checkAuthorization(auth()->user(), ['budget_control.create']);
$users = Admin::getUserByRoleName('Area Manager Cabang');
return view('backend.pages.budget_control.create', [
'users' => $users,
]);
}
public function store(Request $request)
{
$this->checkAuthorization(auth()->user(), ['budget_control.create']);
$validated = $request->validate([
'receiver_id' => 'required|exists:admins,id',
'periode_month' => 'required|string|in:january,february,march,april,may,june,july,august,september,october,november,december',
'periode_year' => 'required|numeric',
'amount' => 'required|numeric',
'remarks' => 'nullable|string',
'closing_at' => 'required|date',
]);
$cabang_id = Admin::find($validated['receiver_id'])->getMyCabangAndRegionId()['cabang'];
BudgetControl::updateOrCreate(['cabang_id' => $cabang_id],
[
'sender_id' => auth()->user()->id,
'receiver_id' => $validated['receiver_id'],
'periode_month' => $validated['periode_month'],
'periode_year' => $validated['periode_year'],
'amount' => $validated['amount'],
'remarks' => $validated['remarks'],
'closing_at' => $validated['closing_at'],
'status' => 'Assigned',
]);
BudgetControlLog::create([
'cabang_id' => $cabang_id,
'sender_id' => auth()->user()->id,
'receiver_id' => $validated['receiver_id'],
'periode_month' => $validated['periode_month'],
'periode_year' => $validated['periode_year'],
'amount' => $validated['amount'],
'remarks' => $validated['remarks'],
'closing_at' => $validated['closing_at'],
'status' => 'Assigned',
]);
session()->flash('success', 'Budget has been added or updated successfully');
return redirect()->route('budget_control');
}
public function destroy($id)
{
$this->checkAuthorization(auth()->user(), ['budget_control.delete']);
$budgetRequest = BudgetControl::findOrfail($id);
$budgetRequest->delete();
return redirect()->route('budget_control');
}
}
@@ -159,10 +159,11 @@ class FormEntertainmentPresentationController extends Controller
public function edit($id) public function edit($id)
{ {
$this->checkAuthorization(auth()->user(), ['forms.entertainment.edit']); $this->checkAuthorization(auth()->user(), ['forms.entertainment.edit']);
$role = auth()->user()->getRoleNames()[0];
$form = FormEntertaimentPresentation::findOrfail($id); $form = FormEntertaimentPresentation::findOrfail($id);
if($form->status == 'Closed') { if($form->status != 'On Progress' && $role == 'Medical Representatif') {
session()->flash('error', 'Form has been closed, you cannot edit it.'); session()->flash('error', 'You cannot edit this form because it has been approved or rejected.');
return redirect()->back(); return redirect()->back();
} }
@@ -174,6 +175,7 @@ class FormEntertainmentPresentationController extends Controller
public function update(Request $request, $id) public function update(Request $request, $id)
{ {
$this->checkAuthorization(auth()->user(), ['forms.entertainment.edit']); $this->checkAuthorization(auth()->user(), ['forms.entertainment.edit']);
$role = auth()->user()->getRoleNames()[0];
$request->validate([ $request->validate([
'tanggal' => 'required', 'tanggal' => 'required',
@@ -187,8 +189,8 @@ class FormEntertainmentPresentationController extends Controller
]); ]);
$form = FormEntertaimentPresentation::findOrfail($id); $form = FormEntertaimentPresentation::findOrfail($id);
if($form->status == 'Closed') { if($form->status != 'On Progress' && $role == 'Medical Representatif') {
session()->flash('error', 'Form has been closed, you cannot edit it.'); session()->flash('error', 'You cannot edit this form because it has been approved or rejected.');
return redirect()->back(); return redirect()->back();
} }
@@ -414,8 +416,14 @@ class FormEntertainmentPresentationController extends Controller
public function destroy($id) public function destroy($id)
{ {
$this->checkAuthorization(auth()->user(), ['forms.entertainment.delete']); $this->checkAuthorization(auth()->user(), ['forms.entertainment.delete']);
$role = auth()->user()->getRoleNames()[0];
$form = FormEntertaimentPresentation::findOrfail($id); $form = FormEntertaimentPresentation::findOrfail($id);
if($form->status != 'On Progress' && $role == 'Medical Representatif') {
session()->flash('error', 'You cannot edit this form because it has been approved or rejected.');
return redirect()->back();
}
AuditTrailHelper::AddAuditTrail('Delete', 'Delete Record at Form Entertainment Presentation (' . $form->expense_number . ')'); AuditTrailHelper::AddAuditTrail('Delete', 'Delete Record at Form Entertainment Presentation (' . $form->expense_number . ')');
$form->delete(); $form->delete();
@@ -190,10 +190,11 @@ class FormMeetingSeminarController extends Controller
public function edit($id) public function edit($id)
{ {
$this->checkAuthorization(auth()->user(), ['forms.meeting.edit']); $this->checkAuthorization(auth()->user(), ['forms.meeting.edit']);
$role = auth()->user()->getRoleNames()[0];
$form = FormMeetingSeminar::findOrfail($id); $form = FormMeetingSeminar::findOrfail($id);
if($form->status == 'Closed') { if($form->status != 'On Progress' && $role == 'Medical Representatif') {
session()->flash('error', 'Form has been closed, you cannot edit it.'); session()->flash('error', 'You cannot edit this form because it has been approved or rejected.');
return redirect()->back(); return redirect()->back();
} }
@@ -205,6 +206,7 @@ class FormMeetingSeminarController extends Controller
public function update(Request $request, $id) public function update(Request $request, $id)
{ {
$this->checkAuthorization(auth()->user(), ['forms.meeting.edit']); $this->checkAuthorization(auth()->user(), ['forms.meeting.edit']);
$role = auth()->user()->getRoleNames()[0];
$request->validate([ $request->validate([
'allowance' => 'nullable|numeric', 'allowance' => 'nullable|numeric',
@@ -216,8 +218,8 @@ class FormMeetingSeminarController extends Controller
]); ]);
$form = FormMeetingSeminar::findOrfail($id); $form = FormMeetingSeminar::findOrfail($id);
if($form->status == 'Closed') { if($form->status != 'On Progress' && $role == 'Medical Representatif') {
session()->flash('error', 'Form has been closed, you cannot edit it.'); session()->flash('error', 'You cannot edit this form because it has been approved or rejected.');
return redirect()->back(); return redirect()->back();
} }
@@ -477,8 +479,14 @@ class FormMeetingSeminarController extends Controller
public function destroy($id) public function destroy($id)
{ {
$this->checkAuthorization(auth()->user(), ['forms.meeting.delete']); $this->checkAuthorization(auth()->user(), ['forms.meeting.delete']);
$role = auth()->user()->getRoleNames()[0];
$form = FormMeetingSeminar::findOrfail($id); $form = FormMeetingSeminar::findOrfail($id);
if($form->status != 'On Progress' && $role == 'Medical Representatif') {
session()->flash('error', 'You cannot edit this form because it has been approved or rejected.');
return redirect()->back();
}
AuditTrailHelper::AddAuditTrail('Delete', 'Delete Record at Form Meeting Seminar (' . $form->expense_number . ')'); AuditTrailHelper::AddAuditTrail('Delete', 'Delete Record at Form Meeting Seminar (' . $form->expense_number . ')');
$form->delete(); $form->delete();
@@ -127,7 +127,6 @@ class FormOtherController extends Controller
$bukti_total->getContent(), $bukti_total->getContent(),
$filename $filename
); );
} }
// Generate sequence number and expense number // Generate sequence number and expense number
@@ -156,10 +155,11 @@ class FormOtherController extends Controller
public function edit($id) public function edit($id)
{ {
$this->checkAuthorization(auth()->user(), ['forms.other.edit']); $this->checkAuthorization(auth()->user(), ['forms.other.edit']);
$role = auth()->user()->getRoleNames()[0];
$form = FormOthers::findOrfail($id); $form = FormOthers::findOrfail($id);
if($form->status == 'Closed') { if($form->status != 'On Progress' && $role == 'Medical Representatif') {
session()->flash('error', 'Form has been closed, you cannot edit it.'); session()->flash('error', 'You cannot edit this form because it has been approved or rejected.');
return redirect()->back(); return redirect()->back();
} }
@@ -172,6 +172,7 @@ class FormOtherController extends Controller
public function update(Request $request, $id) public function update(Request $request, $id)
{ {
$this->checkAuthorization(auth()->user(), ['forms.other.edit']); $this->checkAuthorization(auth()->user(), ['forms.other.edit']);
$role = auth()->user()->getRoleNames()[0];
$request->validate([ $request->validate([
'kategori_id' => 'required', 'kategori_id' => 'required',
@@ -182,8 +183,8 @@ class FormOtherController extends Controller
]); ]);
$form = FormOthers::findOrfail($id); $form = FormOthers::findOrfail($id);
if($form->status == 'Closed') { if($form->status != 'On Progress' && $role == 'Medical Representatif') {
session()->flash('error', 'Form has been closed, you cannot edit it.'); session()->flash('error', 'You cannot edit this form because it has been approved or rejected.');
return redirect()->back(); return redirect()->back();
} }
@@ -205,7 +206,6 @@ class FormOtherController extends Controller
$bukti_total->getContent(), $bukti_total->getContent(),
$filename $filename
); );
} }
// Save the form data // Save the form data
@@ -407,8 +407,14 @@ class FormOtherController extends Controller
public function destroy($id) public function destroy($id)
{ {
$this->checkAuthorization(auth()->user(), ['forms.other.delete']); $this->checkAuthorization(auth()->user(), ['forms.other.delete']);
$role = auth()->user()->getRoleNames()[0];
$form = FormOthers::findOrfail($id); $form = FormOthers::findOrfail($id);
if($form->status != 'On Progress' && $role == 'Medical Representatif') {
session()->flash('error', 'You cannot edit this form because it has been approved or rejected.');
return redirect()->back();
}
AuditTrailHelper::AddAuditTrail('Delete', 'Delete Record at Form Entertainment Presentation (' . $form->expense_number . ')'); AuditTrailHelper::AddAuditTrail('Delete', 'Delete Record at Form Entertainment Presentation (' . $form->expense_number . ')');
$form->delete(); $form->delete();
@@ -220,10 +220,11 @@ class FormUpCountryController extends Controller
public function edit($id) public function edit($id)
{ {
$this->checkAuthorization(auth()->user(), ['forms.country.edit']); $this->checkAuthorization(auth()->user(), ['forms.country.edit']);
$role = auth()->user()->getRoleNames()[0];
$form = FormUpCountry::with('rayon')->findOrfail($id); $form = FormUpCountry::with('rayon')->findOrfail($id);
if($form->status == 'Closed') { if($form->status != 'On Progress' && $role == 'Medical Representatif') {
session()->flash('error', 'Form has been closed, you cannot edit it.'); session()->flash('error', 'You cannot edit this form because it has been approved or rejected.');
return redirect()->back(); return redirect()->back();
} }
@@ -236,6 +237,7 @@ class FormUpCountryController extends Controller
public function update(Request $request, $id) public function update(Request $request, $id)
{ {
$this->checkAuthorization(auth()->user(), ['forms.country.edit']); $this->checkAuthorization(auth()->user(), ['forms.country.edit']);
$role = auth()->user()->getRoleNames()[0];
$request->validate([ $request->validate([
'rayon_id' => 'required|exists:rayon,id', 'rayon_id' => 'required|exists:rayon,id',
@@ -253,8 +255,8 @@ class FormUpCountryController extends Controller
]); ]);
$form = FormUpCountry::findOrfail($id); $form = FormUpCountry::findOrfail($id);
if($form->status == 'Closed') { if($form->status != 'On Progress' && $role == 'Medical Representatif') {
session()->flash('error', 'Form has been closed, you cannot edit it.'); session()->flash('error', 'You cannot edit this form because it has been approved or rejected.');
return redirect()->back(); return redirect()->back();
} }
@@ -537,6 +539,11 @@ class FormUpCountryController extends Controller
$this->checkAuthorization(auth()->user(), ['forms.country.delete']); $this->checkAuthorization(auth()->user(), ['forms.country.delete']);
$form = FormUpCountry::findOrfail($id); $form = FormUpCountry::findOrfail($id);
if($form->status != 'On Progress' && $role == 'Medical Representatif') {
session()->flash('error', 'You cannot edit this form because it has been approved or rejected.');
return redirect()->back();
}
AuditTrailHelper::AddAuditTrail('Delete', 'Delete Record at Form Entertainment Presentation (' . $form->expense_number . ')'); AuditTrailHelper::AddAuditTrail('Delete', 'Delete Record at Form Entertainment Presentation (' . $form->expense_number . ')');
$form->delete(); $form->delete();
@@ -159,10 +159,11 @@ class FormVehicleController extends Controller
public function edit($id) public function edit($id)
{ {
$this->checkAuthorization(auth()->user(), ['forms.vehicle.edit']); $this->checkAuthorization(auth()->user(), ['forms.vehicle.edit']);
$role = auth()->user()->getRoleNames()[0];
$form = FormVehicleRunningCost::findOrfail($id); $form = FormVehicleRunningCost::findOrfail($id);
if($form->status == 'Closed') { if($form->status != 'On Progress' && $role == 'Medical Representatif') {
session()->flash('error', 'Form has been closed, you cannot edit it.'); session()->flash('error', 'You cannot edit this form because it has been approved or rejected.');
return redirect()->back(); return redirect()->back();
} }
@@ -174,6 +175,7 @@ class FormVehicleController extends Controller
public function update(Request $request, $id) public function update(Request $request, $id)
{ {
$this->checkAuthorization(auth()->user(), ['forms.vehicle.edit']); $this->checkAuthorization(auth()->user(), ['forms.vehicle.edit']);
$role = auth()->user()->getRoleNames()[0];
$request->validate([ $request->validate([
'tanggal' => 'required', 'tanggal' => 'required',
@@ -187,8 +189,8 @@ class FormVehicleController extends Controller
]); ]);
$form = FormVehicleRunningCost::findOrfail($id); $form = FormVehicleRunningCost::findOrfail($id);
if($form->status == 'Closed') { if($form->status != 'On Progress' && $role == 'Medical Representatif') {
session()->flash('error', 'Form has been closed, you cannot edit it.'); session()->flash('error', 'You cannot edit this form because it has been approved or rejected.');
return redirect()->back(); return redirect()->back();
} }
@@ -210,7 +212,6 @@ class FormVehicleController extends Controller
$bukti_total->getContent(), $bukti_total->getContent(),
$filename $filename
); );
} }
// Save the form data // Save the form data
@@ -415,8 +416,14 @@ class FormVehicleController extends Controller
public function destroy($id) public function destroy($id)
{ {
$this->checkAuthorization(auth()->user(), ['forms.vehicle.delete']); $this->checkAuthorization(auth()->user(), ['forms.vehicle.delete']);
$role = auth()->user()->getRoleNames()[0];
$form = FormVehicleRunningCost::findOrfail($id); $form = FormVehicleRunningCost::findOrfail($id);
if($form->status != 'On Progress' && $role == 'Medical Representatif') {
session()->flash('error', 'You cannot edit this form because it has been approved or rejected.');
return redirect()->back();
}
AuditTrailHelper::AddAuditTrail('Delete', 'Delete Record at Form Entertainment Presentation (' . $form->expense_number . ')'); AuditTrailHelper::AddAuditTrail('Delete', 'Delete Record at Form Entertainment Presentation (' . $form->expense_number . ')');
$form->delete(); $form->delete();
+12
View File
@@ -8,6 +8,7 @@ use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable; use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Spatie\Permission\Traits\HasRoles; use Spatie\Permission\Traits\HasRoles;
use Spatie\Permission\Models\Role;
class Admin extends Authenticatable class Admin extends Authenticatable
{ {
@@ -155,4 +156,15 @@ class Admin extends Authenticatable
{ {
return $this->hasOne(UserHasCabang::class, 'user_id')->with('cabang'); return $this->hasOne(UserHasCabang::class, 'user_id')->with('cabang');
} }
public static function getUserByRoleName($roleName)
{
$role = Role::where('name', $roleName)->first();
if ($role) {
return $role->users()->with('cabang')->get();
}
return [];
}
} }
+45
View File
@@ -0,0 +1,45 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class BudgetControl extends Model
{
use SoftDeletes;
protected $table = 'budget_control';
protected $fillable = [
'cabang_id',
'sender_id',
'receiver_id',
'amount',
'remarks',
'periode_month',
'periode_year',
'transferred_at',
'closing_at',
'status',
];
public function user()
{
return $this->belongsTo(Admin::class, 'user_id');
}
public function cabang()
{
return $this->belongsTo(Cabang::class, 'cabang_id');
}
public function sender()
{
return $this->belongsTo(Admin::class, 'sender_id');
}
public function receiver()
{
return $this->belongsTo(Admin::class, 'receiver_id');
}
}
+45
View File
@@ -0,0 +1,45 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class BudgetControlLog extends Model
{
use SoftDeletes;
protected $table = 'budget_control_log';
protected $fillable = [
'cabang_id',
'sender_id',
'receiver_id',
'amount',
'remarks',
'periode_month',
'periode_year',
'transferred_at',
'closing_at',
'status',
];
public function user()
{
return $this->belongsTo(Admin::class, 'user_id');
}
public function cabang()
{
return $this->belongsTo(Cabang::class, 'cabang_id');
}
public function sender()
{
return $this->belongsTo(Admin::class, 'sender_id');
}
public function receiver()
{
return $this->belongsTo(Admin::class, 'receiver_id');
}
}
@@ -0,0 +1,44 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('budget_control', function (Blueprint $table) {
$table->id();
$table->foreignId('cabang_id')->nullable()->constrained('cabang');
$table->foreignId('sender_id')->constrained('admins');
$table->foreignId('receiver_id')->constrained('admins');
$table->integer('amount');
$table->string('remarks')->nullable();
$table->string('periode_month');
$table->integer('periode_year');
$table->timestamp('transferred_at')->nullable();
$table->timestamp('closing_at')->nullable();
$table->string('status')->default('Unassigned');
$table->timestamps();
$table->softDeletes();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('budget_control');
}
};
@@ -0,0 +1,44 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('budget_control_log', function (Blueprint $table) {
$table->id();
$table->foreignId('cabang_id')->nullable()->constrained('cabang');
$table->foreignId('sender_id')->constrained('admins');
$table->foreignId('receiver_id')->constrained('admins');
$table->integer('amount');
$table->string('remarks')->nullable();
$table->string('periode_month');
$table->integer('periode_year');
$table->timestamp('transferred_at')->nullable();
$table->timestamp('closing_at')->nullable();
$table->string('status')->default('Unassigned');
$table->timestamps();
$table->softDeletes();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('budget_control_log');
}
};
+3 -1
View File
@@ -10,6 +10,7 @@ use Database\Seeds\RolePermissionSeeder2;
use Database\Seeds\RolePermissionSeeder3; use Database\Seeds\RolePermissionSeeder3;
use Database\Seeds\RolePermissionSeeder4; use Database\Seeds\RolePermissionSeeder4;
use Database\Seeds\RolePermissionSeeder5; use Database\Seeds\RolePermissionSeeder5;
use Database\Seeds\RolePermissionSeeder6;
class DatabaseSeeder extends Seeder class DatabaseSeeder extends Seeder
{ {
@@ -28,6 +29,7 @@ class DatabaseSeeder extends Seeder
// $this->call(RolePermissionSeeder2::class); // $this->call(RolePermissionSeeder2::class);
// $this->call(RolePermissionSeeder3::class); // $this->call(RolePermissionSeeder3::class);
// $this->call(RolePermissionSeeder4::class); // $this->call(RolePermissionSeeder4::class);
$this->call(RolePermissionSeeder5::class); // $this->call(RolePermissionSeeder5::class);
$this->call(RolePermissionSeeder6::class);
} }
} }
+79
View File
@@ -0,0 +1,79 @@
<?php
namespace Database\Seeds;
use App\Models\Admin;
use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
class RolePermissionSeeder6 extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
/**
* Enable these options if you need same role and other permission for User Model
* Else, please follow the below steps for admin guard
*/
$permissions = [
[
'group_name' => 'budget_control',
'permissions' => [
'budget_control.view',
'budget_control.create',
'budget_control.edit',
'budget_control.delete',
'budget_control.approve',
]
],
];
// Do same for the admin guard for tutorial purposes.
$admin = Admin::where('username', 'superadmin')->first();
$roleSuperAdmin = $this->maybeCreateSuperAdminRole($admin);
// Create and Assign Permissions
for ($i = 0; $i < count($permissions); $i++) {
$permissionGroup = $permissions[$i]['group_name'];
for ($j = 0; $j < count($permissions[$i]['permissions']); $j++) {
$permissionExist = Permission::where('name', $permissions[$i]['permissions'][$j])->first();
if (is_null($permissionExist)) {
$permission = Permission::create(
[
'name' => $permissions[$i]['permissions'][$j],
'group_name' => $permissionGroup,
'guard_name' => 'admin'
]
);
$roleSuperAdmin->givePermissionTo($permission);
$permission->assignRole($roleSuperAdmin);
}
}
}
// Assign super admin role permission to superadmin user
if ($admin) {
$admin->assignRole($roleSuperAdmin);
}
}
private function maybeCreateSuperAdminRole($admin): Role
{
if (is_null($admin)) {
$roleSuperAdmin = Role::create(['name' => 'superadmin', 'guard_name' => 'admin']);
} else {
$roleSuperAdmin = Role::where('name', 'superadmin')->where('guard_name', 'admin')->first();
}
if (is_null($roleSuperAdmin)) {
$roleSuperAdmin = Role::create(['name' => 'superadmin', 'guard_name' => 'admin']);
}
return $roleSuperAdmin;
}
}
@@ -0,0 +1,107 @@
@extends('layouts.app')
@section('title')
Dashboard
@endsection
@section('admin-content')
<script src="https://cdn.jsdelivr.net/npm/autonumeric@4.6.0/dist/autoNumeric.min.js"></script>
<section class="content-header">
<div class="container-fluid">
<div class="row mb-2">
<div class="col-sm-6">
<h1>Transfer Budgets</h1>
</div>
<div class="col-sm-6">
<ol class="breadcrumb float-sm-right">
<li class="breadcrumb-item"><a href="{{ route('dashboard.index') }}">Dashboard</a></li>
</li>
</ol>
</div>
</div>
</div>
</section>
<section class="content">
<div class="container-fluid">
<div class="card card-primary card-outline">
<div class="card-body">
<form method="POST" action="{{ route('budget_control.store') }}" enctype="multipart/form-data">
@csrf
@include('backend.layouts.partials.messages')
<div class="row">
<div class="col-lg-6">
<div class="mb-3">
<label class="form-label">Periode Bulan <span class="font-italic font-weight-normal">(required)</span></label>
<select class="form-control form-control-md" name="periode_month" required>
<option value="">Pilih Bulan</option>
<option value="january" {{ old('periode_month') == 1 ? 'selected' : '' }}>Januari</option>
<option value="february" {{ old('periode_month') == 2 ? 'selected' : '' }}>Februari</option>
<option value="march" {{ old('periode_month') == 3 ? 'selected' : '' }}>Maret</option>
<option value="april" {{ old('periode_month') == 4 ? 'selected' : '' }}>April</option>
<option value="may" {{ old('periode_month') == 5 ? 'selected' : '' }}>Mei</option>
<option value="june" {{ old('periode_month') == 6 ? 'selected' : '' }}>Juni</option>
<option value="july" {{ old('periode_month') == 7 ? 'selected' : '' }}>Juli</option>
<option value="august" {{ old('periode_month') == 8 ? 'selected' : '' }}>Agustus</option>
<option value="september" {{ old('periode_month') == 9 ? 'selected' : '' }}>September</option>
<option value="october" {{ old('periode_month') == 10 ? 'selected' : '' }}>Oktober</option>
<option value="november" {{ old('periode_month') == 11 ? 'selected' : '' }}>November</option>
<option value="december" {{ old('periode_month') == 12 ? 'selected' : '' }}>Desember</option>
</select>
</div>
<div class="mb-3">
<label class="form-label">Periode Tahun <span class="font-italic font-weight-normal">(required)</span></label>
<select class="form-control form-control-md" name="periode_year" required>
<option value="">Pilih Tahun</option>
{{-- get current year and one year after --}}
@for ($i = date('Y'); $i <= date('Y') + 1; $i++)
<option value="{{ $i }}" {{ old('periode_year') == $i ? 'selected' : '' }}>{{ $i }}</option>
@endfor
</select>
</div>
<div class="mb-3">
<label class="form-label">Penerima <span class="font-italic font-weight-normal">(required)</span></label>
<select class="form-control form-control-md" name="receiver_id" required>
<option value="">Pilih Receiver</option>
@foreach ($users as $receiver)
<option value="{{ $receiver->id }}" {{ old('receiver_id') == $receiver->id ? 'selected' : '' }}>
{{ $receiver->name }} ({{ $receiver->cabang->cabang->name }})
</option>
@endforeach
</select>
</div>
</div>
<div class="col-lg-6">
<div class="mb-3">
<label class="form-label">Amount <span class="font-italic font-weight-normal">(required)</span></label>
<input type="text" class="form-control" name="amount" id="amount" required value="{{ old('amount') }}">
</div>
<div class="mb-3">
<label class="form-label">Remarks <span class="font-italic font-weight-normal">(optional)</span></label>
<textarea class="form-control" name="remarks">{{ old('remarks') }}</textarea>
</div>
<div class="mb-3">
<label class="form-label">Tanggal Closing <span class="font-italic font-weight-normal">(required)</span></label>
<input type="datetime-local" class="form-control" name="closing_at" id="closing_at" required value="{{ old('closing_at') }}">
</div>
</div>
<button type="submit" class="btn btn-primary ml-2">Submit</button>
</div>
</form>
</div>
</div>
</div>
</section>
<script>
new AutoNumeric('#amount', {
digitGroupSeparator: '.', // Pemisah ribuan
decimalCharacter: ',', // Karakter desimal (tidak digunakan karena tanpa desimal)
currencySymbol: 'Rp.', // Simbol mata uang
decimalPlaces: 0, // Tidak ada angka desimal
unformatOnSubmit: true // Nilai asli tanpa format saat dikirimkan
});
</script>
@endsection
@@ -0,0 +1,150 @@
@extends('layouts.app')
@section('title')
Dashboard
@endsection
@section('admin-content')
<section class="content-header">
<div class="container-fluid">
<div class="row mb-2">
<div class="col-sm-6">
<h1>Active Budgets</h1>
</div>
<div class="col-sm-6">
<ol class="breadcrumb float-sm-right">
<li class="breadcrumb-item"><a href="{{ route('dashboard.index') }}">Dashboard</a></li>
</li>
</ol>
</div>
</div>
</div>
</section>
<section class="content">
<div class="container-fluid">
<div class="row">
<div class="col-lg-4 col-6">
<div class="small-box bg-info">
<div class="inner">
<h3>Rp {{ number_format($data->whereIn('status', 'Assigned')->sum('amount'), 0, ',', '.') }}</h3>
<p>Total Budget Bulan Ini</p>
</div>
<div class="icon">
<i class="fas fa-wallet"></i>
</div>
</div>
</div>
<div class="col-lg-4 col-6">
<div class="small-box bg-success">
<div class="inner">
<h3>Rp {{ number_format($availableBudget, 0, ',', '.') }}</h3>
<p>Total Budget Tersedia</p>
</div>
<div class="icon">
<i class="fas fa-check-circle"></i>
</div>
</div>
</div>
<div class="col-lg-4 col-6">
<div class="small-box bg-danger">
<div class="inner">
<h3 class="text-white">Rp {{ number_format($usedBudget, 0, ',', '.') }}</h3>
<p class="text-white">Total Budget Terpakai</p>
</div>
<div class="icon">
<i class="fas fa-times"></i>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="content">
<div class="container-fluid">
<div class="card card-primary card-outline">
<div class="card-body">
<h4 class="header-title float-left">Current Active Budget</h4>
<p class="float-right mb-2">
@if (auth()->user()->can('budget_control.create'))
<a class="btn btn-primary text-white" href="{{ route('budget_control.create') }}">
Add New Budget
</a>
@endif
</p>
<div class="clearfix"></div>
<div class="dataTables_wrapper dt-bootstrap4 mt-2">
@include('backend.layouts.partials.messages')
<div class="table-responsive">
<table id="dataTable"
class="table table-bordered table-striped table-head-fixed dataTable dtr-inline"
style="width:100%">
<thead class="bg-light text-capitalize">
<tr>
<th>#</th>
<th>Penerima</th>
<th>Cabang</th>
<th>Pengirim</th>
<th>Total</th>
<th>Keterangan</th>
<th>Periode</th>
<th>Tanggal Closing</th>
<th>Status</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
@foreach ($data as $item)
<tr>
<td>{{ $loop->iteration }}</td>
<td>{{ $item->receiver->name }}</td>
<td>{{ $item->cabang->name }}</td>
<td>{{ $item->sender->name }}</td>
<td>{{ number_format($item->amount, 0, ',', '.') }}</td>
<td>{{ $item->remarks }}</td>
<td>{{ strtoupper($item->periode_month) }} {{ $item->periode_year }}</td>
<td>{{ \Carbon\Carbon::parse($item->closing_at)->locale('id')->isoFormat('D MMMM Y H:mm') }}</td>
<td>
@if ($item->status == 'Unassigned')
<span class="badge badge-warning text-white">{{ $item->status }}</span>
@elseif ($item->status == 'Assigned')
<span class="badge badge-success text-white">{{ $item->status }}</span>
@else
<span class="badge badge-danger text-white">{{ $item->status }}</span>
@endif
</td>
<td>
@if (auth()->user()->can('budget_control.delete'))
<form action="{{ route('budget_control.destroy', $item->id) }}" method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this item?');">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-danger btn-sm">
<i class="fas fa-trash"></i>
</button>
</form>
@endif
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</section>
@endsection
@section('scripts')
<script>
$(document).ready(function () {
if ($('#dataTable').length) {
$('#dataTable').DataTable({
responsive: false,
dom: 'Bfrtip',
buttons: ['excel', 'pdf', 'print']
});
}
});
</script>
@endsection
@@ -0,0 +1,92 @@
@extends('layouts.app')
@section('title')
Dashboard
@endsection
@section('admin-content')
<section class="content-header">
<div class="container-fluid">
<div class="row mb-2">
<div class="col-sm-6">
<h1>Log Transfer Budgets</h1>
</div>
<div class="col-sm-6">
<ol class="breadcrumb float-sm-right">
<li class="breadcrumb-item"><a href="{{ route('dashboard.index') }}">Dashboard</a></li>
</li>
</ol>
</div>
</div>
</div>
</section>
<section class="content">
<div class="container-fluid">
<div class="card card-primary card-outline">
<div class="card-body">
<h4 class="header-title float-left">Log Transfer Budgets</h4>
<div class="clearfix"></div>
<div class="dataTables_wrapper dt-bootstrap4 mt-2">
@include('backend.layouts.partials.messages')
<div class="table-responsive">
<table id="dataTable"
class="table table-bordered table-striped table-head-fixed dataTable dtr-inline"
style="width:100%">
<thead class="bg-light text-capitalize">
<tr>
<th>#</th>
<th>Penerima</th>
<th>Cabang</th>
<th>Pengirim</th>
<th>Total</th>
<th>Keterangan</th>
<th>Periode</th>
<th>Tanggal Closing</th>
<th>Status</th>
</tr>
</thead>
<tbody>
@foreach ($data as $item)
<tr>
<td>{{ $loop->iteration }}</td>
<td>{{ $item->receiver->name }}</td>
<td>{{ $item->cabang->name }}</td>
<td>{{ $item->sender->name }}</td>
<td>{{ number_format($item->amount, 0, ',', '.') }}</td>
<td>{{ $item->remarks }}</td>
<td>{{ strtoupper($item->periode_month) }} {{ $item->periode_year }}</td>
<td>{{ \Carbon\Carbon::parse($item->closing_at)->locale('id')->isoFormat('D MMMM Y H:mm') }}</td>
<td>
@if ($item->status == 'Unassigned')
<span class="badge badge-warning text-white">{{ $item->status }}</span>
@elseif ($item->status == 'Assigned')
<span class="badge badge-success text-white">{{ $item->status }}</span>
@else
<span class="badge badge-danger text-white">{{ $item->status }}</span>
@endif
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</section>
@endsection
@section('scripts')
<script>
$(document).ready(function () {
if ($('#dataTable').length) {
$('#dataTable').DataTable({
responsive: false,
dom: 'Bfrtip',
buttons: ['excel', 'pdf', 'print']
});
}
});
</script>
@endsection
@@ -106,6 +106,7 @@
<tbody> <tbody>
@php @php
use App\Helpers\NextCloudHelper; use App\Helpers\NextCloudHelper;
$role = auth()->user()->getRoleNames()[0];
@endphp @endphp
@foreach ($forms as $item) @foreach ($forms as $item)
<tr> <tr>
@@ -201,13 +202,13 @@
</a> </a>
@endif @endif
@if (auth()->user()->can('forms.entertainment.edit')) @if (($role != 'Medical Representatif' && auth()->user()->can('forms.entertainment.edit')) || ($role == 'Medical Representatif' && $item->status == 'On Progress'))
<a href="{{ route('forms.entertainment.edit', $item->id) }}" class="btn btn-warning btn-sm"> <a href="{{ route('forms.entertainment.edit', $item->id) }}" class="btn btn-warning btn-sm">
<i class="fas fa-edit text-white"></i> <i class="fas fa-edit text-white"></i>
</a> </a>
@endif @endif
@if (auth()->user()->can('forms.entertainment.delete')) @if (($role != 'Medical Representatif' && auth()->user()->can('forms.entertainment.delete')) || ($role == 'Medical Representatif' && $item->status == 'On Progress'))
<form action="{{ route('forms.entertainment.destroy', $item->id) }}" method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this item?');"> <form action="{{ route('forms.entertainment.destroy', $item->id) }}" method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this item?');">
@csrf @csrf
@method('DELETE') @method('DELETE')
@@ -106,6 +106,7 @@
<tbody> <tbody>
@php @php
use App\Helpers\NextCloudHelper; use App\Helpers\NextCloudHelper;
$role = auth()->user()->getRoleNames()[0];
@endphp @endphp
@foreach ($forms as $item) @foreach ($forms as $item)
<tr> <tr>
@@ -193,13 +194,13 @@
</a> </a>
@endif @endif
@if (auth()->user()->can('forms.meeting.edit')) @if (($role != 'Medical Representatif' && auth()->user()->can('forms.meeting.edit')) || ($role == 'Medical Representatif' && $item->status == 'On Progress'))
<a href="{{ route('forms.meeting.edit', $item->id) }}" class="btn btn-warning btn-sm"> <a href="{{ route('forms.meeting.edit', $item->id) }}" class="btn btn-warning btn-sm">
<i class="fas fa-edit text-white"></i> <i class="fas fa-edit text-white"></i>
</a> </a>
@endif @endif
@if (auth()->user()->can('forms.meeting.delete')) @if (($role != 'Medical Representatif' && auth()->user()->can('forms.meeting.delete')) || ($role == 'Medical Representatif' && $item->status == 'On Progress'))
<form action="{{ route('forms.meeting.destroy', $item->id) }}" method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this item?');"> <form action="{{ route('forms.meeting.destroy', $item->id) }}" method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this item?');">
@csrf @csrf
@method('DELETE') @method('DELETE')
@@ -104,6 +104,7 @@
<tbody style="width: 100%"> <tbody style="width: 100%">
@php @php
use App\Helpers\NextCloudHelper; use App\Helpers\NextCloudHelper;
$role = auth()->user()->getRoleNames()[0];
@endphp @endphp
@foreach ($forms as $item) @foreach ($forms as $item)
<tr> <tr>
@@ -197,13 +198,13 @@
</a> </a>
@endif @endif
@if (auth()->user()->can('forms.other.edit')) @if (($role != 'Medical Representatif' && auth()->user()->can('forms.other.edit')) || ($role == 'Medical Representatif' && $item->status == 'On Progress'))
<a href="{{ route('forms.other.edit', $item->id) }}" class="btn btn-warning btn-sm"> <a href="{{ route('forms.other.edit', $item->id) }}" class="btn btn-warning btn-sm">
<i class="fas fa-edit text-white"></i> <i class="fas fa-edit text-white"></i>
</a> </a>
@endif @endif
@if (auth()->user()->can('forms.other.delete')) @if (($role != 'Medical Representatif' && auth()->user()->can('forms.other.delete')) || ($role == 'Medical Representatif' && $item->status == 'On Progress'))
<form action="{{ route('forms.other.destroy', $item->id) }}" method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this item?');"> <form action="{{ route('forms.other.destroy', $item->id) }}" method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this item?');">
@csrf @csrf
@method('DELETE') @method('DELETE')
@@ -106,6 +106,7 @@
<tbody> <tbody>
@php @php
use App\Helpers\NextCloudHelper; use App\Helpers\NextCloudHelper;
$role = auth()->user()->getRoleNames()[0];
@endphp @endphp
@foreach ($forms as $item) @foreach ($forms as $item)
<tr> <tr>
@@ -199,13 +200,13 @@
</a> </a>
@endif @endif
@if (auth()->user()->can('forms.country.edit')) @if (($role != 'Medical Representatif' && auth()->user()->can('forms.country.edit')) || ($role == 'Medical Representatif' && $item->status == 'On Progress'))
<a href="{{ route('forms.up-country.edit', $item->id) }}" class="btn btn-warning btn-sm"> <a href="{{ route('forms.up-country.edit', $item->id) }}" class="btn btn-warning btn-sm">
<i class="fas fa-edit text-white"></i> <i class="fas fa-edit text-white"></i>
</a> </a>
@endif @endif
@if (auth()->user()->can('forms.country.delete')) @if (($role != 'Medical Representatif' && auth()->user()->can('forms.country.delete')) || ($role == 'Medical Representatif' && $item->status == 'On Progress'))
<form action="{{ route('forms.up-country.destroy', $item->id) }}" method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this item?');"> <form action="{{ route('forms.up-country.destroy', $item->id) }}" method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this item?');">
@csrf @csrf
@method('DELETE') @method('DELETE')
@@ -107,6 +107,7 @@
<tbody> <tbody>
@php @php
use App\Helpers\NextCloudHelper; use App\Helpers\NextCloudHelper;
$role = auth()->user()->getRoleNames()[0];
@endphp @endphp
@foreach ($forms as $item) @foreach ($forms as $item)
<tr> <tr>
@@ -203,13 +204,13 @@
</a> </a>
@endif @endif
@if (auth()->user()->can('forms.vehicle.edit')) @if (($role != 'Medical Representatif' && auth()->user()->can('forms.vehicle.edit')) || ($role == 'Medical Representatif' && $item->status == 'On Progress'))
<a href="{{ route('forms.vehicle.edit', $item->id) }}" class="btn btn-warning btn-sm"> <a href="{{ route('forms.vehicle.edit', $item->id) }}" class="btn btn-warning btn-sm">
<i class="fas fa-edit text-white"></i> <i class="fas fa-edit text-white"></i>
</a> </a>
@endif @endif
@if (auth()->user()->can('forms.vehicle.delete')) @if (($role != 'Medical Representatif' && auth()->user()->can('forms.vehicle.delete')) || ($role == 'Medical Representatif' && $item->status == 'On Progress'))
<form action="{{ route('forms.vehicle.destroy', $item->id) }}" method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this item?');"> <form action="{{ route('forms.vehicle.destroy', $item->id) }}" method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this item?');">
@csrf @csrf
@method('DELETE') @method('DELETE')
+7
View File
@@ -78,6 +78,13 @@
<a class="d-block font-weight-bold" style="font-size: 11px;"> <a class="d-block font-weight-bold" style="font-size: 11px;">
{{ Auth::guard('admin')->user()->getRoleNames()[0] }} {{ Auth::guard('admin')->user()->getRoleNames()[0] }}
</a> </a>
@if(auth()->user()->getMyCabangAndRegion()['cabang'] != '-')
<a class="d-block" style="font-size: 14px;">
<span class="badge badge-primary">
{{ auth()->user()->getMyCabangAndRegion()['cabang'] }}
</span>
</a>
@endif
</div> </div>
</div> </div>
@include('layouts.partials.sidebar') @include('layouts.partials.sidebar')
+13 -2
View File
@@ -16,9 +16,8 @@ use App\Http\Controllers\Forms\FormVehicleController;
use App\Http\Controllers\Forms\FormEntertainmentPresentationController; use App\Http\Controllers\Forms\FormEntertainmentPresentationController;
use App\Http\Controllers\Forms\FormMeetingSeminarController; use App\Http\Controllers\Forms\FormMeetingSeminarController;
use App\Http\Controllers\Forms\FormOtherController; use App\Http\Controllers\Forms\FormOtherController;
use Illuminate\Support\Facades\Storage;
use App\Helpers\NextCloudHelper;
use App\Http\Controllers\Backend\AuditTrailController; use App\Http\Controllers\Backend\AuditTrailController;
use App\Http\Controllers\Backend\BudgetControlController;
Auth::routes(); Auth::routes();
@@ -72,6 +71,18 @@ Route::group(['prefix' => 'admin', 'as' => 'admin.', 'middleware' => ['auth:admi
Route::middleware(['auth:admin', 'menu'])->group(function () { Route::middleware(['auth:admin', 'menu'])->group(function () {
Route::get('/', [DashboardController::class, 'index'])->name('dashboard.index'); Route::get('/', [DashboardController::class, 'index'])->name('dashboard.index');
Route::prefix('budgets')->group(function () {
Route::get('/', [BudgetControlController::class, 'index'])->name('budget_control');
Route::get('/log', [BudgetControlController::class, 'log'])->name('budget_control.log');
Route::get('/detail/{id}', [BudgetControlController::class, 'detail'])->name('budget_control.detail');
Route::get('/view/{id}', [BudgetControlController::class, 'view'])->name('budget_control.view');
Route::get('/create', [BudgetControlController::class, 'create'])->name('budget_control.create');
Route::post('/store', [BudgetControlController::class, 'store'])->name('budget_control.store');
Route::get('/edit/{id}', [BudgetControlController::class, 'edit'])->name('budget_control.edit');
Route::put('/update/{id}', [BudgetControlController::class, 'update'])->name('budget_control.update');
Route::delete('/destroy/{id}', [BudgetControlController::class, 'destroy'])->name('budget_control.destroy');
});
// Forms // Forms
Route::prefix('forms')->group(function () { Route::prefix('forms')->group(function () {
// Up Country // Up Country