Merge branch 'branch-jagad' into 'main'

Branch jagad

See merge request fiqhpratama1/xpendify!3
This commit is contained in:
FIQH PRATAMA
2024-12-26 04:25:23 +00:00
49 changed files with 4631 additions and 160 deletions
+11 -8
View File
@@ -1,4 +1,4 @@
APP_NAME=Laravel
APP_NAME=Xpendify
APP_ENV=local
APP_KEY=base64:nkxevDI1XtmExvpntHABxwR+rjZ5TMIcXAUxgntuKdM=
APP_DEBUG=true
@@ -51,13 +51,13 @@ REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=log
MAIL_HOST=127.0.0.1
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS="hello@example.com"
MAIL_MAILER=smtp
MAIL_HOST=mail.tia-pharma.com
MAIL_PORT=465
MAIL_USERNAME="mkt.alert@tia-pharma.com"
MAIL_PASSWORD="alert!2024"
MAIL_ENCRYPTION=ssl
MAIL_FROM_ADDRESS="mkt.alert@tia-pharma.com"
MAIL_FROM_NAME="${APP_NAME}"
AWS_ACCESS_KEY_ID=
@@ -72,3 +72,6 @@ NEXT_CLOUD_URL=https://mkt.tunggal-pharma.com
NEXT_CLOUD_USERNAME=user_dev
NEXT_CLOUD_PASSWORD=userdev12345
NEXT_CLOUD_PATHPREFIX=""
WABLAS_HOST=https://bdg.wablas.com
WABLAS_TOKEN=5iCaiP0nEgfl3lzrdsZGb9TvNYuwFZF8s4rp8AYwCx5OrYeiKXgixFMo9nDWNrJN
+62
View File
@@ -0,0 +1,62 @@
<?php
namespace App\Helpers;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
use Illuminate\Support\Str;
class WhatsappHelper
{
public static function approveExpense($phones, $expense_number)
{
$client = new Client();
$data = [];
foreach ($phones as $phone) {
$data[] = [
'phone' => $phone,
'message' => 'Pengajuan pengeluaran anda dengan nomor *' . $expense_number . '* telah disetujui. Silahkan buka website untuk melihat detailnya.',
'source' => 'web'
];
}
$response = $client->post(env('WABLAS_HOST') . '/api/v2/send-message', [
'headers' => [
'Authorization' => env('WABLAS_TOKEN'),
'Content-Type' => 'application/json'
],
'json' => [
'data' => $data
]
]);
return $response->getBody()->getContents();
}
public static function rejectExpense($phones, $expense_number)
{
$client = new Client();
$data = [];
foreach ($phones as $phone) {
$data[] = [
'phone' => $phone,
'message' => 'Pengajuan pengeluaran anda dengan nomor *' . $expense_number . '* telah ditolak. Silahkan buka website untuk melihat detailnya.',
'source' => 'web'
];
}
$response = $client->post(env('WABLAS_HOST') . '/api/v2/send-message', [
'headers' => [
'Authorization' => env('WABLAS_TOKEN'),
'Content-Type' => 'application/json'
],
'json' => [
'data' => $data
]
]);
return $response->getBody()->getContents();
}
}
@@ -12,6 +12,11 @@ use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Hash;
use Spatie\Permission\Models\Role;
use App\Helpers\NextcloudHelper;
use App\Models\FormUpCountry;
use App\Models\FormEntertaimentPresentation;
use App\Models\FormVehicleRunningCost;
use App\Models\FormOthers;
use App\Models\FormMeetingSeminar;
class AdminsController extends Controller
{
@@ -65,15 +70,18 @@ class AdminsController extends Controller
}
// Create a folder in Nextcloud
$response = NextcloudHelper::createUser(env('NEXT_CLOUD_URL'), env('NEXT_CLOUD_USERNAME'), env('NEXT_CLOUD_PASSWORD'), $request->username, $request->password, $request->name, $request->email);
// $response = NextcloudHelper::createUser(env('NEXT_CLOUD_URL'), env('NEXT_CLOUD_USERNAME'), env('NEXT_CLOUD_PASSWORD'), $request->username, $request->password, $request->name, $request->email);
if ($response['success']) {
session()->flash('success', __('Admin has been created.'));
return redirect()->route('admin.admins.index');
} else {
session()->flash('error', $response['message']);
return redirect()->route('admin.admins.index');
}
// if ($response['success']) {
// session()->flash('success', __('Admin has been created.'));
// return redirect()->route('admin.admins.index');
// } else {
// session()->flash('error', $response['message']);
// return redirect()->route('admin.admins.index');
// }
session()->flash('success', 'Admin has been created.');
return redirect()->route('admin.admins.index');
}
public function edit(int $id): Renderable
@@ -118,6 +126,33 @@ class AdminsController extends Controller
return redirect()->route('admin.admins.index');
}
public function expense($user_id)
{
$formUpCountry = FormUpCountry::where('user_id', $user_id)->get();
$formEntertaimentPresentation = FormEntertaimentPresentation::where('user_id', $user_id)->get();
$formVehicleRunningCost = FormVehicleRunningCost::where('user_id', $user_id)->get();
$formOthers = FormOthers::where('user_id', $user_id)->get();
$formMeetingSeminar = FormMeetingSeminar::where('user_id', $user_id)->get();
// Combine all forms into a single array with keys for each form type
$forms = [
'form_up_country' => $formUpCountry,
'form_entertainment_presentation' => $formEntertaimentPresentation,
'form_vehicle_running_cost' => $formVehicleRunningCost,
'form_others' => $formOthers,
'form_meeting_seminar' => $formMeetingSeminar,
];
// Pass the forms and page information to the view
return view('backend.pages.admins.expense', [
'pageInfo' => [
'title' => 'Form Management',
],
'forms' => $forms,
]);
}
public function destroy(int $id): RedirectResponse
{
$this->checkAuthorization(auth()->user(), ['admin.delete']);
@@ -14,6 +14,10 @@ use App\Models\UserHasCabang;
use App\Models\Kategori;
use App\Helpers\NextCloudHelper;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Mail;
use App\Mail\ExpenseApproved;
use App\Mail\ExpenseRejected;
use App\Helpers\WhatsappHelper;
class FormEntertainmentPresentationController extends Controller
{
@@ -21,7 +25,16 @@ class FormEntertainmentPresentationController extends Controller
{
$this->checkAuthorization(auth()->user(), ['forms.entertainment.view']);
$forms = FormEntertaimentPresentation::where('user_id', auth()->user()->id)->get();
// get user role
$role = auth()->user()->getRoleNames()[0];
$forms = null;
if($role == 'Marketing Information System' || $role == 'superadmin') {
$forms = FormEntertaimentPresentation::get();
} else {
$forms = FormEntertaimentPresentation::where('user_id', auth()->user()->id)->get();
}
return view('backend.pages.forms.entertainment.index', [
'forms' => $forms
]);
@@ -120,7 +133,7 @@ class FormEntertainmentPresentationController extends Controller
]);
session()->flash('success', 'Form has been created.');
return redirect()->route('forms.entertainment');
return redirect()->back();
}
public function edit($id)
@@ -128,6 +141,11 @@ class FormEntertainmentPresentationController extends Controller
$this->checkAuthorization(auth()->user(), ['forms.entertainment.edit']);
$form = FormEntertaimentPresentation::findOrfail($id);
if($form->status == 'Closed') {
session()->flash('error', 'Form has been closed, you cannot edit it.');
return redirect()->back();
}
return view('backend.pages.forms.entertainment.edit', [
'form' => $form
]);
@@ -150,7 +168,13 @@ class FormEntertainmentPresentationController extends Controller
'bukti3' => 'nullable|file|mimes:pdf',
]);
$cabang = UserHasCabang::with('cabang')->where('user_id', auth()->user()->id)->first()->cabang;
$form = FormEntertaimentPresentation::findOrfail($id);
if($form->status == 'Closed') {
session()->flash('error', 'Form has been closed, you cannot edit it.');
return redirect()->back();
}
$cabang = UserHasCabang::with('cabang')->where('user_id', $form->user_id)->first()->cabang;
$region = Region::where('id', $cabang->region_id)->first();
$kategori = Kategori::where('name', 'Entertainment & Presentation')->first();
@@ -196,7 +220,6 @@ class FormEntertainmentPresentationController extends Controller
}
// Save the form data
$form = FormEntertaimentPresentation::findOrfail($id);
$form->update([
'tanggal' => $request->tanggal,
'jenis' => $request->jenis,
@@ -209,13 +232,145 @@ class FormEntertainmentPresentationController extends Controller
'bukti2' => $filePaths['bukti2'] ?? null,
'bukti3' => $filePaths['bukti3'] ?? null,
'account_number' => $kategori->account_number,
'status' => 'On Progress',
]);
session()->flash('success', 'Form has been updated.');
return redirect()->route('forms.entertainment');
return redirect()->back();
}
public function approve($id)
{
$this->checkAuthorization(auth()->user(), ['approval.approve']);
$form = FormEntertaimentPresentation::findOrfail($id);
$form->update([
'approved_at' => now(),
'approved_by' => auth()->user()->id,
'status' => 'Approved'
]);
$heads = $form->user->getCabangAndRegionHead();
$name = $form->user->name;
$expense_number = $form->expense_number;
$tanggal = $form->tanggal;
$total = $form->total;
// Collect all recipients
$recipients = [$form->user->email];
$phoneNumbers = [$form->user->phone];
if ($heads['cabang_head']) {
$recipients[] = $heads['cabang_head']['email'];
$phoneNumbers[] = $heads['cabang_head']['phone'];
}
if ($heads['region_head']) {
$recipients[] = $heads['region_head']['email'];
$phoneNumbers[] = $heads['region_head']['phone'];
}
// Remove duplicate email addresses, if any
$recipients = array_unique($recipients);
$phoneNumbers = array_unique($phoneNumbers);
// Send bulk email
Mail::to($recipients)->send(new ExpenseApproved(
$name,
$expense_number,
$tanggal,
$total
));
// Send bulk whatsapp
WhatsappHelper::approveExpense($phoneNumbers, $expense_number);
session()->flash('success', 'Form has been approved.');
return redirect()->back();
}
public function finalApprove($id)
{
$this->checkAuthorization(auth()->user(), ['final_approval.approve']);
$form = FormEntertaimentPresentation::findOrfail($id);
if($form->approved_at == null) {
session()->flash('error', 'Form must be approved by MIS first.');
return redirect()->back();
}
$form->update([
'final_approved_at' => now(),
'final_approved_by' => auth()->user()->id,
'status' => 'Closed'
]);
session()->flash('success', 'Form has been final approved.');
return redirect()->back();
}
public function open($id)
{
$this->checkAuthorization(auth()->user(), ['final_approval.approve']);
$form = FormEntertaimentPresentation::findOrfail($id);
$form->update([
'final_approved_at' => null,
'final_approved_by' => null,
'status' => 'Approved'
]);
session()->flash('success', 'Form has been opened.');
return redirect()->back();
}
public function reject($id)
{
$this->checkAuthorization(auth()->user(), ['approval.approve']);
$form = FormEntertaimentPresentation::findOrfail($id);
$form->update([
'status' => 'Rejected'
]);
$heads = $form->user->getCabangAndRegionHead();
$name = $form->user->name;
$expense_number = $form->expense_number;
$tanggal = $form->tanggal;
$total = $form->total;
// Collect all recipients
$recipients = [$form->user->email];
$phoneNumbers = [$form->user->phone];
if ($heads['cabang_head']) {
$recipients[] = $heads['cabang_head']['email'];
$phoneNumbers[] = $heads['cabang_head']['phone'];
}
if ($heads['region_head']) {
$recipients[] = $heads['region_head']['email'];
$phoneNumbers[] = $heads['region_head']['phone'];
}
// Remove duplicate email addresses, if any
$recipients = array_unique($recipients);
$phoneNumbers = array_unique($phoneNumbers);
// Send bulk email
Mail::to($recipients)->send(new ExpenseRejected(
$name,
$expense_number,
$tanggal,
$total
));
// Send bulk whatsapp
WhatsappHelper::rejectExpense($phoneNumbers, $expense_number);
session()->flash('success', 'Form has been rejected.');
return redirect()->back();
}
public function destroy($id)
{
$this->checkAuthorization(auth()->user(), ['forms.entertainment.delete']);
@@ -224,6 +379,6 @@ class FormEntertainmentPresentationController extends Controller
$form->delete();
session()->flash('success', 'Form has been deleted.');
return redirect()->route('forms.entertainment');
return redirect()->back();
}
}
@@ -14,14 +14,27 @@ use App\Models\UserHasCabang;
use App\Models\Kategori;
use App\Helpers\NextCloudHelper;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Mail;
use App\Mail\ExpenseApproved;
use App\Mail\ExpenseRejected;
use App\Helpers\WhatsappHelper;
class FormMeetingSeminarController extends Controller
{
public function index()
{
$this->checkAuthorization(auth()->user(), ['forms.meeting.view']);
// get user role
$role = auth()->user()->getRoleNames()[0];
$forms = null;
if($role == 'Marketing Information System' || $role == 'superadmin') {
$forms = FormMeetingSeminar::get();
} else {
$forms = FormMeetingSeminar::where('user_id', auth()->user()->id)->get();
}
$forms = FormMeetingSeminar::where('user_id', auth()->user()->id)->get();
return view('backend.pages.forms.meeting.index', [
'forms' => $forms
]);
@@ -42,7 +55,6 @@ class FormMeetingSeminarController extends Controller
'allowance' => 'required',
'transport_ankot' => 'required',
'hotel' => 'required',
'total' => 'required',
'bukti1' => 'nullable|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
'bukti2' => 'nullable|file|mimes:xlsx,xls,csv',
'bukti3' => 'nullable|file|mimes:pdf',
@@ -105,7 +117,7 @@ class FormMeetingSeminarController extends Controller
'allowance' => $request->allowance,
'transport_ankot' => $request->transport_ankot,
'hotel' => $request->hotel,
'total' => $request->total,
'total' => $request->allowance + $request->transport_ankot + $request->hotel,
'bukti1' => $filePaths['bukti1'] ?? null,
'bukti2' => $filePaths['bukti2'] ?? null,
'bukti3' => $filePaths['bukti3'] ?? null,
@@ -114,7 +126,7 @@ class FormMeetingSeminarController extends Controller
]);
session()->flash('success', 'Form has been created.');
return redirect()->route('forms.meeting');
return redirect()->back();
}
public function edit($id)
@@ -122,6 +134,11 @@ class FormMeetingSeminarController extends Controller
$this->checkAuthorization(auth()->user(), ['forms.meeting.edit']);
$form = FormMeetingSeminar::findOrfail($id);
if($form->status == 'Closed') {
session()->flash('error', 'Form has been closed, you cannot edit it.');
return redirect()->back();
}
return view('backend.pages.forms.meeting.edit', [
'form' => $form
]);
@@ -135,13 +152,18 @@ class FormMeetingSeminarController extends Controller
'allowance' => 'required',
'transport_ankot' => 'required',
'hotel' => 'required',
'total' => 'required',
'bukti1' => 'nullable|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
'bukti2' => 'nullable|file|mimes:xlsx,xls,csv',
'bukti3' => 'nullable|file|mimes:pdf',
]);
$cabang = UserHasCabang::with('cabang')->where('user_id', auth()->user()->id)->first()->cabang;
$form = FormMeetingSeminar::findOrfail($id);
if($form->status == 'Closed') {
session()->flash('error', 'Form has been closed, you cannot edit it.');
return redirect()->back();
}
$cabang = UserHasCabang::with('cabang')->where('user_id', $form->user_id)->first()->cabang;
$region = Region::where('id', $cabang->region_id)->first();
$kategori = Kategori::where('name', 'Meeting & Seminar')->first();
@@ -187,23 +209,154 @@ class FormMeetingSeminarController extends Controller
}
// Save the form data
$form = FormMeetingSeminar::findOrfail($id);
$form->update([
'allowance' => $request->allowance,
'transport_ankot' => $request->transport_ankot,
'hotel' => $request->hotel,
'total' => $request->total,
'total' => $request->allowance + $request->transport_ankot + $request->hotel,
'bukti1' => $filePaths['bukti1'] ?? $form->bukti1,
'bukti2' => $filePaths['bukti2'] ?? $form->bukti2,
'bukti3' => $filePaths['bukti3'] ?? $form->bukti3,
'account_number' => $kategori->account_number,
'status' => 'On Progress',
]);
session()->flash('success', 'Form has been updated.');
return redirect()->route('forms.meeting');
return redirect()->back();
}
public function approve($id)
{
$this->checkAuthorization(auth()->user(), ['approval.approve']);
$form = FormMeetingSeminar::findOrfail($id);
$form->update([
'approved_at' => now(),
'approved_by' => auth()->user()->id,
'status' => 'Approved'
]);
$heads = $form->user->getCabangAndRegionHead();
$name = $form->user->name;
$expense_number = $form->expense_number;
$tanggal = $form->tanggal;
$total = $form->total;
// Collect all recipients
$recipients = [$form->user->email];
$phoneNumbers = [$form->user->phone];
if ($heads['cabang_head']) {
$recipients[] = $heads['cabang_head']['email'];
$phoneNumbers[] = $heads['cabang_head']['phone'];
}
if ($heads['region_head']) {
$recipients[] = $heads['region_head']['email'];
$phoneNumbers[] = $heads['region_head']['phone'];
}
// Remove duplicate email addresses, if any
$recipients = array_unique($recipients);
$phoneNumbers = array_unique($phoneNumbers);
// Send bulk email
Mail::to($recipients)->send(new ExpenseApproved(
$name,
$expense_number,
$tanggal,
$total
));
// Send bulk WhatsApp message
WhatsappHelper::approveExpense($phoneNumbers, $expense_number);
session()->flash('success', 'Form has been approved.');
return redirect()->back();
}
public function finalApprove($id)
{
$this->checkAuthorization(auth()->user(), ['final_approval.approve']);
$form = FormMeetingSeminar::findOrfail($id);
if($form->approved_at == null) {
session()->flash('error', 'Form must be approved by MIS first.');
return redirect()->back();
}
$form->update([
'final_approved_at' => now(),
'final_approved_by' => auth()->user()->id,
'status' => 'Closed'
]);
session()->flash('success', 'Form has been final approved.');
return redirect()->back();
}
public function open($id)
{
$this->checkAuthorization(auth()->user(), ['final_approval.approve']);
$form = FormMeetingSeminar::findOrfail($id);
$form->update([
'final_approved_at' => null,
'final_approved_by' => null,
'status' => 'Approved'
]);
session()->flash('success', 'Form has been opened.');
return redirect()->back();
}
public function reject($id)
{
$this->checkAuthorization(auth()->user(), ['approval.approve']);
$form = FormMeetingSeminar::findOrfail($id);
$form->update([
'status' => 'Rejected'
]);
$heads = $form->user->getCabangAndRegionHead();
$name = $form->user->name;
$expense_number = $form->expense_number;
$tanggal = $form->tanggal;
$total = $form->total;
// Collect all recipients
$recipients = [$form->user->email];
$phoneNumbers = [$form->user->phone];
if ($heads['cabang_head']) {
$recipients[] = $heads['cabang_head']['email'];
$phoneNumbers[] = $heads['cabang_head']['phone'];
}
if ($heads['region_head']) {
$recipients[] = $heads['region_head']['email'];
$phoneNumbers[] = $heads['region_head']['phone'];
}
// Remove duplicate email addresses, if any
$recipients = array_unique($recipients);
$phoneNumbers = array_unique($phoneNumbers);
// Send bulk email
Mail::to($recipients)->send(new ExpenseRejected(
$name,
$expense_number,
$tanggal,
$total
));
// Send bulk WhatsApp message
WhatsappHelper::rejectExpense($phoneNumbers, $expense_number);
session()->flash('success', 'Form has been rejected.');
return redirect()->back();
}
public function destroy($id)
{
$this->checkAuthorization(auth()->user(), ['forms.meeting.delete']);
@@ -212,6 +365,6 @@ class FormMeetingSeminarController extends Controller
$form->delete();
session()->flash('success', 'Form has been deleted.');
return redirect()->route('forms.meeting');
return redirect()->back();
}
}
@@ -0,0 +1,375 @@
<?php
namespace App\Http\Controllers\Forms;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\FormOthers;
use App\Models\Rayon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use App\Models\Region;
use App\Models\Cabang;
use App\Models\UserHasCabang;
use App\Models\Kategori;
use Illuminate\Support\Str;
use App\Helpers\NextCloudHelper;
use Illuminate\Support\Facades\Mail;
use App\Mail\ExpenseApproved;
use App\Mail\ExpenseRejected;
use App\Helpers\WhatsappHelper;
class FormOtherController extends Controller
{
public function index()
{
$this->checkAuthorization(auth()->user(), ['forms.other.view']);
// get user role
$role = auth()->user()->getRoleNames()[0];
$forms = null;
if($role == 'Marketing Information System' || $role == 'superadmin') {
$forms = FormOthers::get();
} else {
$forms = FormOthers::where('user_id', auth()->user()->id)->get();
}
return view('backend.pages.forms.other.index', [
'forms' => $forms
]);
}
public function create()
{
$this->checkAuthorization(auth()->user(), ['forms.other.create']);
return view('backend.pages.forms.other.create', [
'kategori' => Kategori::whereNotIn('name', ['Up Country', 'Vehicle Running Cost', 'Entertainment & Presentation', 'Meeting & Seminar'])->get()
]);
}
public function store(Request $request)
{
$this->checkAuthorization(auth()->user(), ['forms.other.create']);
$request->validate([
'kategori_id' => 'required',
'tanggal' => 'required|date',
'keterangan' => 'required',
'total' => 'required',
'bukti1' => 'nullable|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
'bukti2' => 'nullable|file|mimes:xlsx,xls,csv',
'bukti3' => 'nullable|file|mimes:pdf',
]);
$cabang = UserHasCabang::with('cabang')->where('user_id', auth()->user()->id)->first()->cabang;
$region = Region::where('id', $cabang->region_id)->first();
$kategori = Kategori::where('id', $request->kategori_id)->first();
$filePaths = [];
$folderPath = '/expense/' . $region->code . '/' . $cabang->code . '/other';
if ($request->hasFile('bukti1')) {
$bukti1 = $request->file('bukti1');
$filename = Str::uuid() . '.' . $bukti1->extension();
$filePaths['bukti1'] = $folderPath . '/' . $filename;
NextCloudHelper::uploadFile(
$folderPath,
$bukti1->getContent(),
$filename
);
}
if ($request->hasFile('bukti2')) {
$bukti2 = $request->file('bukti2');
$filename = Str::uuid() . '.' . $bukti2->extension();
$filePaths['bukti2'] = $folderPath . '/' . $filename;
NextCloudHelper::uploadFile(
$folderPath,
$bukti2->getContent(),
$filename
);
}
if ($request->hasFile('bukti3')) {
$bukti3 = $request->file('bukti3');
$filename = Str::uuid() . '.' . $bukti3->extension();
$filePaths['bukti3'] = $folderPath . '/' . $filename;
NextCloudHelper::uploadFile(
$folderPath,
$bukti3->getContent(),
$filename
);
}
// Generate sequence number and expense number
$sequence_number = FormOthers::withTrashed()->where('expense_number', 'like', $region->code . '-' . $cabang->code . '-OTH-' . date('ym') . '%')->count() + 1;
$formatted_sequence_number = str_pad($sequence_number, 4, '0', STR_PAD_LEFT);
$expense_number = $region->code . '-' . $cabang->code . '-OTH-' . date('ym') . $formatted_sequence_number;
// Save the form data
FormOthers::create([
'expense_number' => $expense_number,
'user_id' => auth()->user()->id,
'kategori_id' => $request->kategori_id,
'tanggal' => $request->tanggal,
'keterangan' => $request->keterangan,
'total' => $request->total,
'bukti1' => $filePaths['bukti1'] ?? null,
'bukti2' => $filePaths['bukti2'] ?? null,
'bukti3' => $filePaths['bukti3'] ?? null,
'account_number' => $kategori->account_number,
'status' => 'On Progress',
]);
session()->flash('success', 'Form has been created.');
return redirect()->back();
}
public function edit($id)
{
$this->checkAuthorization(auth()->user(), ['forms.other.edit']);
$form = FormOthers::findOrfail($id);
if($form->status == 'Closed') {
session()->flash('error', 'Form has been closed, you cannot edit it.');
return redirect()->back();
}
return view('backend.pages.forms.other.edit', [
'form' => $form,
'kategori' => Kategori::whereNotIn('name', ['Up Country', 'Vehicle Running Cost', 'Entertainment & Presentation', 'Meeting & Seminar'])->get()
]);
}
public function update(Request $request, $id)
{
$this->checkAuthorization(auth()->user(), ['forms.other.edit']);
$request->validate([
'kategori_id' => 'required',
'tanggal' => 'required|date',
'keterangan' => 'required',
'total' => 'required',
'bukti1' => 'nullable|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
'bukti2' => 'nullable|file|mimes:xlsx,xls,csv',
'bukti3' => 'nullable|file|mimes:pdf',
]);
$form = FormOthers::findOrfail($id);
if($form->status == 'Closed') {
session()->flash('error', 'Form has been closed, you cannot edit it.');
return redirect()->back();
}
$cabang = UserHasCabang::with('cabang')->where('user_id', $form->user_id)->first()->cabang;
$region = Region::where('id', $cabang->region_id)->first();
$kategori = Kategori::where('id', $request->kategori_id)->first();
$filePaths = [];
$folderPath = '/expense/' . $region->code . '/' . $cabang->code . '/other';
if ($request->hasFile('bukti1')) {
$bukti1 = $request->file('bukti1');
$filename = Str::uuid() . '.' . $bukti1->extension();
$filePaths['bukti1'] = $folderPath . '/' . $filename;
NextCloudHelper::uploadFile(
$folderPath,
$bukti1->getContent(),
$filename
);
}
if ($request->hasFile('bukti2')) {
$bukti2 = $request->file('bukti2');
$filename = Str::uuid() . '.' . $bukti2->extension();
$filePaths['bukti2'] = $folderPath . '/' . $filename;
NextCloudHelper::uploadFile(
$folderPath,
$bukti2->getContent(),
$filename
);
}
if ($request->hasFile('bukti3')) {
$bukti3 = $request->file('bukti3');
$filename = Str::uuid() . '.' . $bukti3->extension();
$filePaths['bukti3'] = $folderPath . '/' . $filename;
NextCloudHelper::uploadFile(
$folderPath,
$bukti3->getContent(),
$filename
);
}
// Save the form data
$form->update([
'kategori_id' => $request->kategori_id,
'tanggal' => $request->tanggal,
'keterangan' => $request->keterangan,
'total' => $request->total,
'bukti1' => $filePaths['bukti1'] ?? $form->bukti1,
'bukti2' => $filePaths['bukti2'] ?? $form->bukti2,
'bukti3' => $filePaths['bukti3'] ?? $form->bukti3,
'account_number' => $kategori->account_number,
]);
session()->flash('success', 'Form has been updated.');
return redirect()->back();
}
public function approve($id)
{
$this->checkAuthorization(auth()->user(), ['approval.approve']);
$form = FormOthers::findOrfail($id);
$form->update([
'approved_at' => now(),
'approved_by' => auth()->user()->id,
'status' => 'Approved'
]);
$heads = $form->user->getCabangAndRegionHead();
$name = $form->user->name;
$expense_number = $form->expense_number;
$tanggal = $form->tanggal;
$total = $form->total;
// Collect all recipients
$recipients = [$form->user->email];
$phoneNumbers = [$form->user->phone];
if ($heads['cabang_head']) {
$recipients[] = $heads['cabang_head']['email'];
$phoneNumbers[] = $heads['cabang_head']['phone'];
}
if ($heads['region_head']) {
$recipients[] = $heads['region_head']['email'];
$phoneNumbers[] = $heads['region_head']['phone'];
}
// Remove duplicate email addresses, if any
$recipients = array_unique($recipients);
$phoneNumbers = array_unique($phoneNumbers);
// Send bulk email
Mail::to($recipients)->send(new ExpenseApproved(
$name,
$expense_number,
$tanggal,
$total
));
// Send bulk WhatsApp message
WhatsappHelper::approveExpense($phoneNumbers, $expense_number);
session()->flash('success', 'Form has been approved.');
return redirect()->back();
}
public function finalApprove($id)
{
$this->checkAuthorization(auth()->user(), ['final_approval.approve']);
$form = FormOthers::findOrfail($id);
if($form->approved_at == null) {
session()->flash('error', 'Form must be approved by MIS first.');
return redirect()->back();
}
$form->update([
'final_approved_at' => now(),
'final_approved_by' => auth()->user()->id,
'status' => 'Closed'
]);
session()->flash('success', 'Form has been final approved.');
return redirect()->back();
}
public function open($id)
{
$this->checkAuthorization(auth()->user(), ['final_approval.approve']);
$form = FormOthers::findOrfail($id);
$form->update([
'final_approved_at' => null,
'final_approved_by' => null,
'status' => 'Approved'
]);
session()->flash('success', 'Form has been opened.');
return redirect()->back();
}
public function reject($id)
{
$this->checkAuthorization(auth()->user(), ['approval.approve']);
$form = FormOthers::findOrfail($id);
$form->update([
'status' => 'Rejected'
]);
$heads = $form->user->getCabangAndRegionHead();
$name = $form->user->name;
$expense_number = $form->expense_number;
$tanggal = $form->tanggal;
$total = $form->total;
// Collect all recipients
$recipients = [$form->user->email];
$phoneNumbers = [$form->user->phone];
if ($heads['cabang_head']) {
$recipients[] = $heads['cabang_head']['email'];
$phoneNumbers[] = $heads['cabang_head']['phone'];
}
if ($heads['region_head']) {
$recipients[] = $heads['region_head']['email'];
$phoneNumbers[] = $heads['region_head']['phone'];
}
// Remove duplicate email addresses, if any
$recipients = array_unique($recipients);
$phoneNumbers = array_unique($phoneNumbers);
// Send bulk email
Mail::to($recipients)->send(new ExpenseRejected(
$name,
$expense_number,
$tanggal,
$total
));
// Send bulk WhatsApp message
WhatsappHelper::rejectExpense($phoneNumbers, $expense_number);
session()->flash('success', 'Form has been rejected.');
return redirect()->back();
}
public function destroy($id)
{
$this->checkAuthorization(auth()->user(), ['forms.other.delete']);
$form = FormOthers::findOrfail($id);
$form->delete();
session()->flash('success', 'Form has been deleted.');
return redirect()->back();
}
}
@@ -14,6 +14,10 @@ use App\Models\UserHasCabang;
use App\Models\Kategori;
use App\Helpers\NextCloudHelper;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Mail;
use App\Mail\ExpenseApproved;
use App\Mail\ExpenseRejected;
use App\Helpers\WhatsappHelper;
class FormUpCountryController extends Controller
{
@@ -21,7 +25,16 @@ class FormUpCountryController extends Controller
{
$this->checkAuthorization(auth()->user(), ['forms.country.view']);
$forms = FormUpCountry::with('rayon')->where('user_id', auth()->user()->id)->get();
// get user role
$role = auth()->user()->getRoleNames()[0];
$forms = null;
if($role == 'Marketing Information System' || $role == 'superadmin') {
$forms = FormUpCountry::with('rayon')->get();
} else {
$forms = FormUpCountry::with('rayon')->where('user_id', auth()->user()->id)->get();
}
return view('backend.pages.forms.upcountry.index', [
'forms' => $forms
]);
@@ -48,8 +61,6 @@ class FormUpCountryController extends Controller
'allowance' => 'required',
'transport_dalkot' => 'required',
'transport_ankot' => 'required',
'hotel' => 'required',
'total' => 'required',
'bukti1' => 'nullable|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
'bukti2' => 'nullable|file|mimes:xlsx,xls,csv',
'bukti3' => 'nullable|file|mimes:pdf',
@@ -117,7 +128,7 @@ class FormUpCountryController extends Controller
'transport_dalkot' => $request->transport_dalkot,
'transport_ankot' => $request->transport_ankot,
'hotel' => $request->hotel,
'total' => $request->total,
'total' => $request->allowance + $request->transport_dalkot + $request->transport_ankot + $request->hotel,
'bukti1' => $filePaths['bukti1'] ?? null,
'bukti2' => $filePaths['bukti2'] ?? null,
'bukti3' => $filePaths['bukti3'] ?? null,
@@ -126,7 +137,7 @@ class FormUpCountryController extends Controller
]);
session()->flash('success', 'Form has been created.');
return redirect()->route('forms.up-country');
return redirect()->back();
}
public function edit($id)
@@ -134,6 +145,11 @@ class FormUpCountryController extends Controller
$this->checkAuthorization(auth()->user(), ['forms.country.edit']);
$form = FormUpCountry::with('rayon')->findOrfail($id);
if($form->status == 'Closed') {
session()->flash('error', 'Form has been closed, you cannot edit it.');
return redirect()->back();
}
return view('backend.pages.forms.upcountry.edit', [
'rayons' => Rayon::all(),
'form' => $form
@@ -153,13 +169,18 @@ class FormUpCountryController extends Controller
'transport_dalkot' => 'required',
'transport_ankot' => 'required',
'hotel' => 'required',
'total' => 'required',
'bukti1' => 'nullable|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
'bukti2' => 'nullable|file|mimes:xlsx,xls,csv',
'bukti3' => 'nullable|file|mimes:pdf',
]);
$cabang = UserHasCabang::with('cabang')->where('user_id', auth()->user()->id)->first()->cabang;
$form = FormUpCountry::findOrfail($id);
if($form->status == 'Closed') {
session()->flash('error', 'Form has been closed, you cannot edit it.');
return redirect()->back();
}
$cabang = UserHasCabang::with('cabang')->where('user_id', $form->user_id)->first()->cabang;
$region = Region::where('id', $cabang->region_id)->first();
$kategori = Kategori::where('name', 'Up Country')->first();
@@ -205,7 +226,6 @@ class FormUpCountryController extends Controller
}
// Save the form data
$form = FormUpCountry::findOrfail($id);
$form->update([
'rayon_id' => $request->rayon_id,
'tanggal' => $request->tanggal,
@@ -215,18 +235,150 @@ class FormUpCountryController extends Controller
'transport_dalkot' => $request->transport_dalkot,
'transport_ankot' => $request->transport_ankot,
'hotel' => $request->hotel,
'total' => $request->total,
'total' => $request->allowance + $request->transport_dalkot + $request->transport_ankot + $request->hotel,
'bukti1' => $filePaths['bukti1'] ?? $form->bukti1,
'bukti2' => $filePaths['bukti2'] ?? $form->bukti2,
'bukti3' => $filePaths['bukti3'] ?? $form->bukti3,
'account_number' => $kategori->account_number,
'status' => 'On Progress',
]);
session()->flash('success', 'Form has been updated.');
return redirect()->route('forms.up-country');
return redirect()->back();
}
public function approve($id)
{
$this->checkAuthorization(auth()->user(), ['approval.approve']);
$form = FormUpCountry::findOrfail($id);
$form->update([
'approved_at' => now(),
'approved_by' => auth()->user()->id,
'status' => 'Approved'
]);
$heads = $form->user->getCabangAndRegionHead();
$name = $form->user->name;
$expense_number = $form->expense_number;
$tanggal = $form->tanggal;
$total = $form->total;
// Collect all recipients
$recipients = [$form->user->email];
$phoneNumbers = [$form->user->phone];
if ($heads['cabang_head']) {
$recipients[] = $heads['cabang_head']['email'];
$phoneNumbers[] = $heads['cabang_head']['phone'];
}
if ($heads['region_head']) {
$recipients[] = $heads['region_head']['email'];
$phoneNumbers[] = $heads['region_head']['phone'];
}
// Remove duplicate data, if any
$recipients = array_unique($recipients);
$phoneNumbers = array_unique($phoneNumbers);
// // Send bulk email
Mail::to($recipients)->send(new ExpenseApproved(
$name,
$expense_number,
$tanggal,
$total
));
// send whatsapp message
WhatsappHelper::approveExpense($phoneNumbers, $expense_number);
session()->flash('success', 'Form has been approved.');
return redirect()->back();
}
public function reject($id)
{
$this->checkAuthorization(auth()->user(), ['approval.approve']);
$form = FormUpCountry::findOrfail($id);
$form->update([
'status' => 'Rejected'
]);
$heads = $form->user->getCabangAndRegionHead();
$name = $form->user->name;
$expense_number = $form->expense_number;
$tanggal = $form->tanggal;
$total = $form->total;
// Collect all recipients
$recipients = [$form->user->email];
$phoneNumbers = [$form->user->phone];
if ($heads['cabang_head']) {
$recipients[] = $heads['cabang_head']['email'];
$phoneNumbers[] = $heads['cabang_head']['phone'];
}
if ($heads['region_head']) {
$recipients[] = $heads['region_head']['email'];
$phoneNumbers[] = $heads['region_head']['phone'];
}
// Remove duplicate email addresses, if any
$recipients = array_unique($recipients);
$phoneNumbers = array_unique($phoneNumbers);
// Send bulk email
Mail::to($recipients)->send(new ExpenseRejected(
$name,
$expense_number,
$tanggal,
$total
));
// send whatsapp message
WhatsappHelper::rejectExpense($phoneNumbers, $expense_number);
session()->flash('success', 'Form has been rejected.');
return redirect()->back();
}
public function finalApprove($id)
{
$this->checkAuthorization(auth()->user(), ['final_approval.approve']);
$form = FormUpCountry::findOrfail($id);
if($form->approved_at == null) {
session()->flash('error', 'Form must be approved by MIS first.');
return redirect()->back();
}
$form->update([
'final_approved_at' => now(),
'final_approved_by' => auth()->user()->id,
'status' => 'Closed'
]);
session()->flash('success', 'Form has been final approved.');
return redirect()->back();
}
public function open($id)
{
$this->checkAuthorization(auth()->user(), ['final_approval.approve']);
$form = FormUpCountry::findOrfail($id);
$form->update([
'final_approved_at' => null,
'final_approved_by' => null,
'status' => 'Approved'
]);
session()->flash('success', 'Form has been opened.');
return redirect()->back();
}
public function destroy($id)
{
$this->checkAuthorization(auth()->user(), ['forms.country.delete']);
@@ -235,6 +387,6 @@ class FormUpCountryController extends Controller
$form->delete();
session()->flash('success', 'Form has been deleted.');
return redirect()->route('forms.up-country');
return redirect()->back();
}
}
@@ -14,6 +14,10 @@ use App\Models\UserHasCabang;
use App\Models\Kategori;
use App\Helpers\NextCloudHelper;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Mail;
use App\Mail\ExpenseApproved;
use App\Mail\ExpenseRejected;
use App\Helpers\WhatsappHelper;
class FormVehicleController extends Controller
{
@@ -21,7 +25,16 @@ class FormVehicleController extends Controller
{
$this->checkAuthorization(auth()->user(), ['forms.vehicle.view']);
$forms = FormVehicleRunningCost::where('user_id', auth()->user()->id)->get();
// get user role
$role = auth()->user()->getRoleNames()[0];
$forms = null;
if($role == 'Marketing Information System' || $role == 'superadmin') {
$forms = FormVehicleRunningCost::get();
} else {
$forms = FormVehicleRunningCost::where('user_id', auth()->user()->id)->get();
}
return view('backend.pages.forms.vehicle.index', [
'forms' => $forms
]);
@@ -41,7 +54,7 @@ class FormVehicleController extends Controller
$request->validate([
'tanggal' => 'required',
'liter' => 'required',
'harga' => 'required',
'total' => 'required',
'jarak' => 'required',
'tipe_bensin' => 'required|in:pertalite,pertamax',
'nopol' => 'required',
@@ -107,7 +120,7 @@ class FormVehicleController extends Controller
'user_id' => auth()->user()->id,
'tanggal' => $request->tanggal,
'liter' => $request->liter,
'harga' => $request->harga,
'total' => $request->total,
'jarak' => $request->jarak,
'tipe_bensin' => $request->tipe_bensin,
'nopol' => $request->nopol,
@@ -120,7 +133,7 @@ class FormVehicleController extends Controller
]);
session()->flash('success', 'Form has been created.');
return redirect()->route('forms.vehicle');
return redirect()->back();
}
public function edit($id)
@@ -128,6 +141,11 @@ class FormVehicleController extends Controller
$this->checkAuthorization(auth()->user(), ['forms.vehicle.edit']);
$form = FormVehicleRunningCost::findOrfail($id);
if($form->status == 'Closed') {
session()->flash('error', 'Form has been closed, you cannot edit it.');
return redirect()->back();
}
return view('backend.pages.forms.vehicle.edit', [
'form' => $form
]);
@@ -140,7 +158,7 @@ class FormVehicleController extends Controller
$request->validate([
'tanggal' => 'required',
'liter' => 'required',
'harga' => 'required',
'total' => 'required',
'jarak' => 'required',
'tipe_bensin' => 'required|in:pertalite,pertamax',
'nopol' => 'required',
@@ -150,7 +168,13 @@ class FormVehicleController extends Controller
'bukti3' => 'nullable|file|mimes:pdf',
]);
$cabang = UserHasCabang::with('cabang')->where('user_id', auth()->user()->id)->first()->cabang;
$form = FormVehicleRunningCost::findOrfail($id);
if($form->status == 'Closed') {
session()->flash('error', 'Form has been closed, you cannot edit it.');
return redirect()->back();
}
$cabang = UserHasCabang::with('cabang')->where('user_id', $form->user_id)->first()->cabang;
$region = Region::where('id', $cabang->region_id)->first();
$kategori = Kategori::where('name', 'Vehicle Running Cost')->first();
@@ -196,11 +220,10 @@ class FormVehicleController extends Controller
}
// Save the form data
$form = FormVehicleRunningCost::findOrfail($id);
$form->update([
'tanggal' => $request->tanggal,
'liter' => $request->liter,
'harga' => $request->harga,
'total' => $request->total,
'jarak' => $request->jarak,
'tipe_bensin' => $request->tipe_bensin,
'nopol' => $request->nopol,
@@ -213,9 +236,142 @@ class FormVehicleController extends Controller
]);
session()->flash('success', 'Form has been updated.');
return redirect()->route('forms.vehicle');
return redirect()->back();
}
public function approve($id)
{
$this->checkAuthorization(auth()->user(), ['approval.approve']);
$form = FormVehicleRunningCost::findOrfail($id);
$form->update([
'approved_at' => now(),
'approved_by' => auth()->user()->id,
'status' => 'Approved'
]);
$heads = $form->user->getCabangAndRegionHead();
$name = $form->user->name;
$expense_number = $form->expense_number;
$tanggal = $form->tanggal;
$total = $form->total;
// Collect all recipients
$recipients = [$form->user->email];
$phoneNumbers = [$form->user->phone];
if ($heads['cabang_head']) {
$recipients[] = $heads['cabang_head']['email'];
$phoneNumbers[] = $heads['cabang_head']['phone'];
}
if ($heads['region_head']) {
$recipients[] = $heads['region_head']['email'];
$phoneNumbers[] = $heads['region_head']['phone'];
}
// Remove duplicate email addresses, if any
$recipients = array_unique($recipients);
$phoneNumbers = array_unique($phoneNumbers);
// Send bulk email
Mail::to($recipients)->send(new ExpenseApproved(
$name,
$expense_number,
$tanggal,
$total
));
// Send bulk WhatsApp message
WhatsappHelper::approveExpense($phoneNumbers, $expense_number);
session()->flash('success', 'Form has been approved.');
return redirect()->back();
}
public function finalApprove($id)
{
$this->checkAuthorization(auth()->user(), ['final_approval.approve']);
$form = FormVehicleRunningCost::findOrfail($id);
if($form->approved_at == null) {
session()->flash('error', 'Form must be approved by MIS first.');
return redirect()->back();
}
$form->update([
'final_approved_at' => now(),
'final_approved_by' => auth()->user()->id,
'status' => 'Closed'
]);
session()->flash('success', 'Form has been final approved.');
return redirect()->back();
}
public function open($id)
{
$this->checkAuthorization(auth()->user(), ['final_approval.approve']);
$form = FormVehicleRunningCost::findOrfail($id);
$form->update([
'final_approved_at' => null,
'final_approved_by' => null,
'status' => 'Approved'
]);
session()->flash('success', 'Form has been opened.');
return redirect()->back();
}
public function reject($id)
{
$this->checkAuthorization(auth()->user(), ['approval.approve']);
$form = FormVehicleRunningCost::findOrfail($id);
$form->update([
'status' => 'Rejected'
]);
$heads = $form->user->getCabangAndRegionHead();
$name = $form->user->name;
$expense_number = $form->expense_number;
$tanggal = $form->tanggal;
$total = $form->total;
// Collect all recipients
$recipients = [$form->user->email];
$phoneNumbers = [$form->user->phone];
if ($heads['cabang_head']) {
$recipients[] = $heads['cabang_head']['email'];
$phoneNumbers[] = $heads['cabang_head']['phone'];
}
if ($heads['region_head']) {
$recipients[] = $heads['region_head']['email'];
$phoneNumbers[] = $heads['region_head']['phone'];
}
// Remove duplicate email addresses, if any
$recipients = array_unique($recipients);
$phoneNumbers = array_unique($phoneNumbers);
// Send bulk email
Mail::to($recipients)->send(new ExpenseRejected(
$name,
$expense_number,
$tanggal,
$total
));
// Send bulk WhatsApp message
WhatsappHelper::rejectExpense($phoneNumbers, $expense_number);
session()->flash('success', 'Form has been rejected.');
return redirect()->back();
}
public function destroy($id)
{
$this->checkAuthorization(auth()->user(), ['forms.vehicle.delete']);
@@ -224,6 +380,6 @@ class FormVehicleController extends Controller
$form->delete();
session()->flash('success', 'Form has been deleted.');
return redirect()->route('forms.vehicle');
return redirect()->back();
}
}
+61
View File
@@ -0,0 +1,61 @@
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class ExpenseApproved extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*/
public function __construct(
protected string $name,
protected string $expense_number,
protected string $tanggal,
protected int $total,
) {}
/**
* Get the message envelope.
*/
public function envelope(): Envelope
{
return new Envelope(
subject: 'Expense Approved',
);
}
/**
* Get the message content definition.
*/
public function content(): Content
{
return new Content(
view: 'mail.approved',
with: [
'name' => $this->name,
'expense_number' => $this->expense_number,
'tanggal' => $this->tanggal,
'total' => $this->total,
],
);
}
/**
* Get the attachments for the message.
*
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
*/
public function attachments(): array
{
return [];
}
}
+61
View File
@@ -0,0 +1,61 @@
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class ExpenseRejected extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*/
public function __construct(
protected string $name,
protected string $expense_number,
protected string $tanggal,
protected int $total,
) {}
/**
* Get the message envelope.
*/
public function envelope(): Envelope
{
return new Envelope(
subject: 'Expense Rejected',
);
}
/**
* Get the message content definition.
*/
public function content(): Content
{
return new Content(
view: 'mail.rejected',
with: [
'name' => $this->name,
'expense_number' => $this->expense_number,
'tanggal' => $this->tanggal,
'total' => $this->total,
],
);
}
/**
* Get the attachments for the message.
*
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
*/
public function attachments(): array
{
return [];
}
}
+27
View File
@@ -77,4 +77,31 @@ class Admin extends Authenticatable
}
return $hasPermission;
}
public function getCabangAndRegionHead()
{
// Fetch the UserHasCabang entry for this admin
$userHasCabang = $this->hasOne(UserHasCabang::class, 'user_id')->with('cabang')->first();
if ($userHasCabang && $userHasCabang->cabang) {
$cabang = $userHasCabang->cabang;
// Fetch the cabang head
$cabangHead = $cabang->head;
// Fetch the region and its head
$region = $cabang->region;
$regionHead = $region ? $region->head : null;
return [
'cabang_head' => $cabangHead,
'region_head' => $regionHead,
];
}
return [
'cabang_head' => null,
'region_head' => null,
];
}
}
+11
View File
@@ -11,9 +11,20 @@ class Cabang extends Model
protected $table = 'cabang';
protected $fillable = [
'head_id',
'region_id',
'cost_id',
'code',
'name',
];
public function head()
{
return $this->belongsTo(Admin::class, 'head_id');
}
public function region()
{
return $this->belongsTo(Region::class, 'region_id');
}
}
@@ -25,6 +25,10 @@ class FormEntertaimentPresentation extends Model
'bukti3',
'account_number',
'status',
'approved_at',
'approved_by',
'final_approved_at',
'final_approved_by',
];
public function user()
+4
View File
@@ -22,6 +22,10 @@ class FormMeetingSeminar extends Model
'bukti3',
'account_number',
'status',
'approved_at',
'approved_by',
'final_approved_at',
'final_approved_by',
];
public function user()
+15
View File
@@ -20,6 +20,21 @@ class FormOthers extends Model
'bukti1',
'bukti2',
'bukti3',
'account_number',
'status',
'approved_at',
'approved_by',
'final_approved_at',
'final_approved_by',
];
public function user()
{
return $this->belongsTo(Admin::class);
}
public function kategori()
{
return $this->belongsTo(Kategori::class);
}
}
+4
View File
@@ -27,6 +27,10 @@ class FormUpCountry extends Model
'bukti3',
'account_number',
'status',
'approved_at',
'approved_by',
'final_approved_at',
'final_approved_by',
];
public function user()
+5 -1
View File
@@ -15,7 +15,7 @@ class FormVehicleRunningCost extends Model
'user_id',
'tanggal',
'liter',
'harga',
'total',
'jarak',
'tipe_bensin',
'nopol',
@@ -25,6 +25,10 @@ class FormVehicleRunningCost extends Model
'bukti3',
'account_number',
'status',
'approved_at',
'approved_by',
'final_approved_at',
'final_approved_by',
];
public function user()
+6
View File
@@ -11,7 +11,13 @@ class Region extends Model
protected $table = 'region';
protected $fillable = [
'head_id',
'code',
'name',
];
public function head()
{
return $this->belongsTo('App\Models\Admin');
}
}
@@ -17,7 +17,7 @@ return new class extends Migration
$table->foreignId('user_id')->constrained('admins')->cascadeOnDelete();
$table->dateTime('tanggal');
$table->integer('liter');
$table->integer('harga');
$table->integer('total');
$table->integer('jarak');
$table->string('tipe_bensin');
$table->string('nopol');
@@ -0,0 +1,28 @@
<?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::table('form_others', function (Blueprint $table) {
$table->string('account_number')->nullable()->after('total');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('form_others', function (Blueprint $table) {
$table->dropColumn('account_number');
});
}
};
@@ -0,0 +1,39 @@
<?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::table('form_up_country', function (Blueprint $table) {
// normal approval
$table->timestamp('approved_at')->nullable()->after('status');
$table->foreignId('approved_by')->nullable()->constrained('admins')->cascadeOnDelete()->after('status');
// final approval
$table->timestamp('final_approved_at')->nullable()->after('status');
$table->foreignId('final_approved_by')->nullable()->constrained('admins')->cascadeOnDelete()->after('status');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('form_up_country', function (Blueprint $table) {
$table->dropForeign(['approved_by']);
$table->dropForeign(['final_approved_by']);
$table->dropColumn('approved_at');
$table->dropColumn('approved_by');
$table->dropColumn('final_approved_at');
$table->dropColumn('final_approved_by');
});
}
};
@@ -0,0 +1,39 @@
<?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::table('form_vehicle_running_cost', function (Blueprint $table) {
// normal approval
$table->timestamp('approved_at')->nullable()->after('status');
$table->foreignId('approved_by')->nullable()->constrained('admins')->cascadeOnDelete()->after('status');
// final approval
$table->timestamp('final_approved_at')->nullable()->after('status');
$table->foreignId('final_approved_by')->nullable()->constrained('admins')->cascadeOnDelete()->after('status');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('form_vehicle_running_cost', function (Blueprint $table) {
$table->dropForeign(['approved_by']);
$table->dropForeign(['final_approved_by']);
$table->dropColumn('approved_at');
$table->dropColumn('approved_by');
$table->dropColumn('final_approved_at');
$table->dropColumn('final_approved_by');
});
}
};
@@ -0,0 +1,39 @@
<?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::table('form_entertainment_presentation', function (Blueprint $table) {
// normal approval
$table->timestamp('approved_at')->nullable()->after('status');
$table->foreignId('approved_by')->nullable()->constrained('admins')->cascadeOnDelete()->after('status');
// final approval
$table->timestamp('final_approved_at')->nullable()->after('status');
$table->foreignId('final_approved_by')->nullable()->constrained('admins')->cascadeOnDelete()->after('status');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('form_entertainment_presentation', function (Blueprint $table) {
$table->dropForeign(['approved_by']);
$table->dropForeign(['final_approved_by']);
$table->dropColumn('approved_at');
$table->dropColumn('approved_by');
$table->dropColumn('final_approved_at');
$table->dropColumn('final_approved_by');
});
}
};
@@ -0,0 +1,39 @@
<?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::table('form_meeting_seminar', function (Blueprint $table) {
// normal approval
$table->timestamp('approved_at')->nullable()->after('status');
$table->foreignId('approved_by')->nullable()->constrained('admins')->cascadeOnDelete()->after('status');
// final approval
$table->timestamp('final_approved_at')->nullable()->after('status');
$table->foreignId('final_approved_by')->nullable()->constrained('admins')->cascadeOnDelete()->after('status');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('form_meeting_seminar', function (Blueprint $table) {
$table->dropForeign(['approved_by']);
$table->dropForeign(['final_approved_by']);
$table->dropColumn('approved_at');
$table->dropColumn('approved_by');
$table->dropColumn('final_approved_at');
$table->dropColumn('final_approved_by');
});
}
};
@@ -0,0 +1,39 @@
<?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::table('form_others', function (Blueprint $table) {
// normal approval
$table->timestamp('approved_at')->nullable()->after('status');
$table->foreignId('approved_by')->nullable()->constrained('admins')->cascadeOnDelete()->after('status');
// final approval
$table->timestamp('final_approved_at')->nullable()->after('status');
$table->foreignId('final_approved_by')->nullable()->constrained('admins')->cascadeOnDelete()->after('status');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('form_others', function (Blueprint $table) {
$table->dropForeign(['approved_by']);
$table->dropForeign(['final_approved_by']);
$table->dropColumn('approved_at');
$table->dropColumn('approved_by');
$table->dropColumn('final_approved_at');
$table->dropColumn('final_approved_by');
});
}
};
@@ -0,0 +1,29 @@
<?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::table('region', function (Blueprint $table) {
$table->foreignId('head_id')->nullable()->constrained('admins')->onDelete('set null')->after('id');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('region', function (Blueprint $table) {
$table->dropForeign(['head_id']);
$table->dropColumn('head_id');
});
}
};
@@ -0,0 +1,29 @@
<?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::table('cabang', function (Blueprint $table) {
$table->foreignId('head_id')->nullable()->constrained('admins')->onDelete('set null')->after('id');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('cabang', function (Blueprint $table) {
$table->dropForeign(['head_id']);
$table->dropColumn('head_id');
});
}
};
+3 -1
View File
@@ -8,6 +8,7 @@ use Database\Seeds\MenuSeeder;
use Database\Seeds\RayonSeeder;
use Database\Seeds\RolePermissionSeeder2;
use Database\Seeds\RolePermissionSeeder3;
use Database\Seeds\RolePermissionSeeder4;
class DatabaseSeeder extends Seeder
{
@@ -24,6 +25,7 @@ class DatabaseSeeder extends Seeder
// $this->call(MenuSeeder::class);
// $this->call(RayonSeeder::class);
// $this->call(RolePermissionSeeder2::class);
$this->call(RolePermissionSeeder3::class);
// $this->call(RolePermissionSeeder3::class);
$this->call(RolePermissionSeeder4::class);
}
}
+90
View File
@@ -0,0 +1,90 @@
<?php
namespace Database\Seeds;
use App\Models\Admin;
use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
/**
* Class RolePermissionSeeder.
*
* @see https://spatie.be/docs/laravel-permission/v5/basic-usage/multiple-guards
*
* @package App\Database\Seeds
*/
class RolePermissionSeeder4 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' => 'approval',
'permissions' => [
'approval.view',
'approval.approve',
]
],
[
'group_name' => 'final_approval',
'permissions' => [
'final_approval.view',
'final_approval.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,838 @@
@extends('layouts.app')
@section('title')
{{ $pageInfo['title'] }}
@endsection
@section('admin-content')
<section class="content-header">
<div class="container-fluid">
<div class="row mb-2">
<div class="col-sm-6">
<h1>{{ $pageInfo['title'] }}</h1>
</div>
<div class="col-sm-6">
<ol class="breadcrumb float-sm-right">
<li class="breadcrumb-form"><a href="{{ route('admin.dashboard') }}">{{ __('Dashboard') }}</a> / </li>
<li class="breadcrumb-form active">&nbsp;{{ $pageInfo['title'] }}</li>
</ol>
</div>
</div>
</div>
</section>
@php
use App\Helpers\NextCloudHelper;
@endphp
<section class="content">
<div class="container-fluid">
<!-- Form Up Country Table -->
<div class="row">
<div class="col-12 mt-5">
<div class="card">
<div class="card-body">
<h4 class="header-title">Form Up Country</h4>
<div class="data-tables">
@include('backend.layouts.partials.messages')
<table id="dataTable-form_up_country">
<thead class="bg-light text-capitalize">
<tr>
<th>#</th>
<th>Nama</th>
<th>Rayon</th>
<th>Tanggal</th>
<th>Tujuan</th>
<th>Jarak</th>
<th>Total</th>
<th>Bukti 1</th>
<th>Bukti 2</th>
<th>Bukti 3</th>
<th>Account Number</th>
<th>Status</th>
@if (auth()->user()->can('approval.approve') || auth()->user()->can('final_approval.approve'))
<th>Approval</th>
@endif
<th>Aksi</th>
</tr>
</thead>
<tbody>
@foreach ($forms['form_up_country'] as $index => $form)
<tr>
<td>{{ $loop->iteration }}</td>
<td>{{ $form->user->name }}</td>
<td>{{ $form->rayon->code }}</td>
<td>{{ \Carbon\Carbon::parse($form->tanggal)->locale('id')->isoFormat('D MMMM Y') }}</td>
<td>{{ $form->tujuan }}</td>
<td>{{ $form->jarak }} km</td>
<td>{{ number_format($form->total, 0, ',', '.') }}</td>
<td>
@if ($form->bukti1)
<a href="{{ NextCloudHelper::getFileUrl($form->bukti1) }}" target="_blank">
Download
</a>
@else
-
@endif
</td>
<td>
@if ($form->bukti2)
<a href="{{ NextCloudHelper::getFileUrl($form->bukti2) }}" target="_blank">
Download
</a>
@else
-
@endif
</td>
<td>
@if ($form->bukti3)
<a href="{{ NextCloudHelper::getFileUrl($form->bukti3) }}" target="_blank">
Download
</a>
@else
-
@endif
</td>
<td>{{ $form->account_number }}</td>
<td>
@if ($form->status == 'On Progress')
<span class="badge badge-warning text-white">{{ $form->status }}</span>
@elseif ($form->status == 'Approved' || $form->status == 'Final Approved')
<span class="badge badge-success text-white">{{ $form->status }}</span>
@else
<span class="badge badge-danger text-white">{{ $form->status }}</span>
@endif
</td>
@if (auth()->user()->can('approval.approve'))
<td>
{{-- approve / reject button --}}
@if ($form->status == 'On Progress')
<form action="{{ route('forms.up-country.approve', $form->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to approve this form?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-success btn-sm">
Approve
</button>
</form>
<form action="{{ route('forms.up-country.reject', $form->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to reject this form?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-danger btn-sm">
Reject
</button>
</form>
@else
@if ($form->approved_at)
{{ \Carbon\Carbon::parse($form->approved_at)->locale('id')->isoFormat('D MMMM Y') }}
@elseif($form->rejected_at)
{{ \Carbon\Carbon::parse($form->rejected_at)->locale('id')->isoFormat('D MMMM Y') }}
@else
-
@endif
@endif
</td>
@elseif(auth()->user()->can('final_approval.approve'))
<td>
{{-- approve / reject button --}}
@if ($form->status == 'Approved' && $form->approved_at && !$form->final_approved_at)
<form action="{{ route('forms.up-country.final-approve', $form->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to approve this form?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-success btn-sm">
Final Approve
</button>
</form>
@else
@if ($form->final_approved_at)
<form action="{{ route('forms.up-country.open', $form->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to approve this form?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-success btn-sm">
Open
</button>
</form>
@else
-
@endif
@endif
</td>
@endif
<td>
@if (auth()->user()->can('forms.country.edit'))
<a href="{{ route('forms.up-country.edit', $form->id) }}" class="btn btn-warning btn-sm">
<i class="fas fa-edit text-white"></i>
</a>
@endif
@if (auth()->user()->can('forms.country.delete'))
<form action="{{ route('forms.up-country.destroy', $form->id) }}" method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this form?');">
@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>
<!-- Form Vehicle Running Cost Table -->
<div class="row">
<div class="col-12 mt-5">
<div class="card">
<div class="card-body">
<h4 class="header-title">Form Vehicle Running Cost</h4>
<div class="data-tables">
<table id="dataTable-form_vehicle_running_cost">
<thead class="bg-light text-capitalize">
<tr>
<th>#</th>
<th>Nama</th>
<th>Tanggal</th>
<th>Liter</th>
<th>Harga</th>
<th>Jarak</th>
<th>Tipe Bensin</th>
<th>Nomor Polisi</th>
<th>Bukti 1</th>
<th>Bukti 2</th>
<th>Bukti 3</th>
<th>Account Number</th>
<th>Status</th>
@if (auth()->user()->can('approval.approve') || auth()->user()->can('final_approval.approve'))
<th>Approval</th>
@endif
<th>Aksi</th>
</tr>
</thead>
<tbody>
@foreach ($forms['form_vehicle_running_cost'] as $index => $form)
<tr>
<td>{{ $loop->iteration }}</td>
<td>{{ $form->user->name }}</td>
<td>{{ \Carbon\Carbon::parse($form->tanggal)->locale('id')->isoFormat('dddd, D MMMM Y HH:mm:ss') }}</td>
<td>{{ $form->liter }}</td>
<td>{{ number_format($form->harga, 0, ',', '.') }}</td>
<td>{{ $form->jarak }}</td>
<td>{{ $form->tipe_bensin }}</td>
<td>{{ $form->nopol }}</td>
<td>
@if ($form->bukti1)
<a href="{{ NextCloudHelper::getFileUrl($form->bukti1) }}" target="_blank">
Download
</a>
@else
-
@endif
</td>
<td>
@if ($form->bukti2)
<a href="{{ NextCloudHelper::getFileUrl($form->bukti2) }}" target="_blank">
Download
</a>
@else
-
@endif
</td>
<td>
@if ($form->bukti3)
<a href="{{ NextCloudHelper::getFileUrl($form->bukti3) }}" target="_blank">
Download
</a>
@else
-
@endif
</td>
<td>{{ $form->account_number }}</td>
<td>
@if ($form->status == 'On Progress')
<span class="badge badge-warning text-white">{{ $form->status }}</span>
@elseif ($form->status == 'Approved' || $form->status == 'Final Approved')
<span class="badge badge-success text-white">{{ $form->status }}</span>
@else
<span class="badge badge-danger text-white">{{ $form->status }}</span>
@endif
</td>
@if (auth()->user()->can('approval.approve'))
<td>
{{-- approve / reject button --}}
@if ($form->status == 'On Progress')
<form action="{{ route('forms.vehicle.approve', $form->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to approve this form?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-success btn-sm">
Approve
</button>
</form>
<form action="{{ route('forms.vehicle.reject', $form->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to reject this form?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-danger btn-sm">
Reject
</button>
</form>
@else
@if ($form->approved_at)
{{ \Carbon\Carbon::parse($form->approved_at)->locale('id')->isoFormat('D MMMM Y') }}
@elseif($form->rejected_at)
{{ \Carbon\Carbon::parse($form->rejected_at)->locale('id')->isoFormat('D MMMM Y') }}
@else
-
@endif
@endif
</td>
@elseif(auth()->user()->can('final_approval.approve'))
<td>
{{-- approve / reject button --}}
@if ($form->status == 'Approved' && $form->approved_at && !$form->final_approved_at)
<form action="{{ route('forms.vehicle.final-approve', $form->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to approve this form?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-success btn-sm">
Final Approve
</button>
</form>
@else
@if ($form->final_approved_at)
<form action="{{ route('forms.vehicle.open', $form->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to approve this form?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-success btn-sm">
Open
</button>
</form>
@else
-
@endif
@endif
</td>
@endif
<td>
@if (auth()->user()->can('forms.vehicle.edit'))
<a href="{{ route('forms.vehicle.edit', $form->id) }}" class="btn btn-warning btn-sm">
<i class="fas fa-edit text-white"></i>
</a>
@endif
@if (auth()->user()->can('forms.vehicle.delete'))
<form action="{{ route('forms.vehicle.destroy', $form->id) }}" method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this form?');">
@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>
<!-- Form Entertainment Presentation Table -->
<div class="row">
<div class="col-12 mt-5">
<div class="card">
<div class="card-body">
<h4 class="header-title">Form Entertainment Presentation</h4>
<div class="data-tables">
<table id="dataTable-form_entertainment_presentation">
<thead class="bg-light text-capitalize">
<tr>
<th>#</th>
<th>Nama</th>
<th>Tanggal</th>
<th>Jenis</th>
<th>Keterangan</th>
<th>Total</th>
<th>Nama Penerima</th>
<th>Bukti 1</th>
<th>Bukti 2</th>
<th>Bukti 3</th>
<th>Account Number</th>
<th>Status</th>
@if (auth()->user()->can('approval.approve') || auth()->user()->can('final_approval.approve'))
<th>Approval</th>
@endif
<th>Aksi</th>
</tr>
</thead>
<tbody>
@foreach ($forms['form_entertainment_presentation'] as $index => $form)
<tr>
<td>{{ $loop->iteration }}</td>
<td>{{ $form->user->name }}</td>
<td>{{ \Carbon\Carbon::parse($form->tanggal)->locale('id')->isoFormat('D MMMM Y') }}</td>
<td>{{ $form->jenis }}</td>
<td>{{ $form->keterangan }}</td>
<td>{{ number_format($form->total, 0, ',', '.') }}</td>
<td>{{ $form->name }}</td>
<td>
@if ($form->bukti1)
<a href="{{ NextCloudHelper::getFileUrl($form->bukti1) }}" target="_blank">
Download
</a>
@else
-
@endif
</td>
<td>
@if ($form->bukti2)
<a href="{{ NextCloudHelper::getFileUrl($form->bukti2) }}" target="_blank">
Download
</a>
@else
-
@endif
</td>
<td>
@if ($form->bukti3)
<a href="{{ NextCloudHelper::getFileUrl($form->bukti3) }}" target="_blank">
Download
</a>
@else
-
@endif
</td>
<td>{{ $form->account_number }}</td>
<td>
@if ($form->status == 'On Progress')
<span class="badge badge-warning text-white">{{ $form->status }}</span>
@elseif ($form->status == 'Approved' || $form->status == 'Final Approved')
<span class="badge badge-success text-white">{{ $form->status }}</span>
@else
<span class="badge badge-danger text-white">{{ $form->status }}</span>
@endif
</td>
@if (auth()->user()->can('approval.approve'))
<td>
{{-- approve / reject button --}}
@if ($form->status == 'On Progress')
<form action="{{ route('forms.entertainment.approve', $form->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to approve this form?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-success btn-sm">
Approve
</button>
</form>
<form action="{{ route('forms.entertainment.reject', $form->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to reject this form?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-danger btn-sm">
Reject
</button>
</form>
@else
@if ($form->approved_at)
{{ \Carbon\Carbon::parse($form->approved_at)->locale('id')->isoFormat('D MMMM Y') }}
@elseif($form->rejected_at)
{{ \Carbon\Carbon::parse($form->rejected_at)->locale('id')->isoFormat('D MMMM Y') }}
@else
-
@endif
@endif
</td>
@elseif(auth()->user()->can('final_approval.approve'))
<td>
{{-- approve / reject button --}}
@if ($form->status == 'Approved' && $form->approved_at && !$form->final_approved_at)
<form action="{{ route('forms.entertainment.final-approve', $form->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to approve this form?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-success btn-sm">
Final Approve
</button>
</form>
@else
@if ($form->final_approved_at)
<form action="{{ route('forms.entertainment.open', $form->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to approve this form?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-success btn-sm">
Open
</button>
</form>
@else
-
@endif
@endif
</td>
@endif
<td>
@if (auth()->user()->can('forms.entertainment.edit'))
<a href="{{ route('forms.entertainment.edit', $form->id) }}" class="btn btn-warning btn-sm">
<i class="fas fa-edit text-white"></i>
</a>
@endif
@if (auth()->user()->can('forms.entertainment.delete'))
<form action="{{ route('forms.entertainment.destroy', $form->id) }}" method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this form?');">
@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>
<!-- Form Meeting Seminar Table -->
<div class="row">
<div class="col-12 mt-5">
<div class="card">
<div class="card-body">
<h4 class="header-title">Form Meeting Seminar</h4>
<div class="data-tables">
<table id="dataTable-form_meeting_seminar">
<thead class="bg-light text-capitalize">
<tr>
<th>#</th>
<th>Nama</th>
<th>Tanggal</th>
<th>Allowance</th>
<th>Transport Ankot</th>
<th>Hotel</th>
<th>Total</th>
<th>Bukti 1</th>
<th>Bukti 2</th>
<th>Bukti 3</th>
<th>Account Number</th>
<th>Status</th>
@if (auth()->user()->can('approval.approve') || auth()->user()->can('final_approval.approve'))
<th>Approval</th>
@endif
<th>Aksi</th>
</tr>
</thead>
<tbody>
@foreach ($forms['form_meeting_seminar'] as $index => $form)
<tr>
<td>{{ $loop->iteration }}</td>
<td>{{ $form->user->name }}</td>
<td>{{ \Carbon\Carbon::parse($form->created_at)->locale('id')->isoFormat('D MMMM Y') }}</td>
<td>{{ number_format($form->allowance, 0, ',', '.') }}</td>
<td>{{ number_format($form->transport_ankot, 0, ',', '.') }}</td>
<td>{{ number_format($form->hotel, 0, ',', '.') }}</td>
<td>{{ number_format($form->total, 0, ',', '.') }}</td>
<td>
@if ($form->bukti1)
<a href="{{ NextCloudHelper::getFileUrl($form->bukti1) }}" target="_blank">
Download
</a>
@else
-
@endif
</td>
<td>
@if ($form->bukti2)
<a href="{{ NextCloudHelper::getFileUrl($form->bukti2) }}" target="_blank">
Download
</a>
@else
-
@endif
</td>
<td>
@if ($form->bukti3)
<a href="{{ NextCloudHelper::getFileUrl($form->bukti3) }}" target="_blank">
Download
</a>
@else
-
@endif
</td>
<td>{{ $form->account_number }}</td>
<td>
@if ($form->status == 'On Progress')
<span class="badge badge-warning text-white">{{ $form->status }}</span>
@elseif ($form->status == 'Approved' || $form->status == 'Final Approved')
<span class="badge badge-success text-white">{{ $form->status }}</span>
@else
<span class="badge badge-danger text-white">{{ $form->status }}</span>
@endif
</td>
@if (auth()->user()->can('approval.approve'))
<td>
{{-- approve / reject button --}}
@if ($form->status == 'On Progress')
<form action="{{ route('forms.meeting.approve', $form->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to approve this form?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-success btn-sm">
Approve
</button>
</form>
<form action="{{ route('forms.meeting.reject', $form->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to reject this form?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-danger btn-sm">
Reject
</button>
</form>
@else
@if ($form->approved_at)
{{ \Carbon\Carbon::parse($form->approved_at)->locale('id')->isoFormat('D MMMM Y') }}
@elseif($form->rejected_at)
{{ \Carbon\Carbon::parse($form->rejected_at)->locale('id')->isoFormat('D MMMM Y') }}
@else
-
@endif
@endif
</td>
@elseif(auth()->user()->can('final_approval.approve'))
<td>
{{-- approve / reject button --}}
@if ($form->status == 'Approved' && $form->approved_at && !$form->final_approved_at)
<form action="{{ route('forms.meeting.final-approve', $form->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to approve this form?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-success btn-sm">
Final Approve
</button>
</form>
@else
@if ($form->final_approved_at)
<form action="{{ route('forms.meeting.open', $form->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to approve this form?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-success btn-sm">
Open
</button>
</form>
@else
-
@endif
@endif
</td>
@endif
<td>
@if (auth()->user()->can('forms.meeting.edit'))
<a href="{{ route('forms.meeting.edit', $form->id) }}" class="btn btn-warning btn-sm">
<i class="fas fa-edit text-white"></i>
</a>
@endif
@if (auth()->user()->can('forms.meeting.delete'))
<form action="{{ route('forms.meeting.destroy', $form->id) }}" method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this form?');">
@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>
<!-- Form Others Table -->
<div class="row">
<div class="col-12 mt-5">
<div class="card">
<div class="card-body">
<h4 class="header-title">Form Others</h4>
<div class="data-tables">
<table id="dataTable-form_others">
<thead class="bg-light text-capitalize">
<tr>
<th>#</th>
<th>Nama</th>
<th>Tanggal</th>
<th>Jenis</th>
<th>Keterangan</th>
<th>Total</th>
<th>Bukti 1</th>
<th>Bukti 2</th>
<th>Bukti 3</th>
<th>Account Number</th>
<th>Status</th>
@if (auth()->user()->can('approval.approve') || auth()->user()->can('final_approval.approve'))
<th>Approval</th>
@endif
<th>Aksi</th>
</tr>
</thead>
<tbody>
@foreach ($forms['form_others'] as $index => $form)
<tr>
<td>{{ $loop->iteration }}</td>
<td>{{ $form->user->name }}</td>
<td>{{ \Carbon\Carbon::parse($form->tanggal)->locale('id')->isoFormat('D MMMM Y') }}</td>
<td>{{ $form->kategori->name }}</td>
<td>{{ $form->keterangan }}</td>
<td>{{ number_format($form->total, 0, ',', '.') }}</td>
<td>
@if ($form->bukti1)
<a href="{{ NextCloudHelper::getFileUrl($form->bukti1) }}" target="_blank">
Download
</a>
@else
-
@endif
</td>
<td>
@if ($form->bukti2)
<a href="{{ NextCloudHelper::getFileUrl($form->bukti2) }}" target="_blank">
Download
</a>
@else
-
@endif
</td>
<td>
@if ($form->bukti3)
<a href="{{ NextCloudHelper::getFileUrl($form->bukti3) }}" target="_blank">
Download
</a>
@else
-
@endif
</td>
<td>{{ $form->account_number }}</td>
<td>
@if ($form->status == 'On Progress')
<span class="badge badge-warning text-white">{{ $form->status }}</span>
@elseif ($form->status == 'Approved' || $form->status == 'Final Approved')
<span class="badge badge-success text-white">{{ $form->status }}</span>
@else
<span class="badge badge-danger text-white">{{ $form->status }}</span>
@endif
</td>
@if (auth()->user()->can('approval.approve'))
<td>
{{-- approve / reject button --}}
@if ($form->status == 'On Progress')
<form action="{{ route('forms.other.approve', $form->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to approve this form?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-success btn-sm">
Approve
</button>
</form>
<form action="{{ route('forms.other.reject', $form->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to reject this form?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-danger btn-sm">
Reject
</button>
</form>
@else
@if ($form->approved_at)
{{ \Carbon\Carbon::parse($form->approved_at)->locale('id')->isoFormat('D MMMM Y') }}
@elseif($form->rejected_at)
{{ \Carbon\Carbon::parse($form->rejected_at)->locale('id')->isoFormat('D MMMM Y') }}
@else
-
@endif
@endif
</td>
@elseif(auth()->user()->can('final_approval.approve'))
<td>
{{-- approve / reject button --}}
@if ($form->status == 'Approved' && $form->approved_at && !$form->final_approved_at)
<form action="{{ route('forms.other.final-approve', $form->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to approve this form?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-success btn-sm">
Final Approve
</button>
</form>
@else
@if ($form->final_approved_at)
<form action="{{ route('forms.other.open', $form->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to approve this form?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-success btn-sm">
Open
</button>
</form>
@else
-
@endif
@endif
</td>
@endif
<td>
@if (auth()->user()->can('forms.other.edit'))
<a href="{{ route('forms.other.edit', $form->id) }}" class="btn btn-warning btn-sm">
<i class="fas fa-edit text-white"></i>
</a>
@endif
@if (auth()->user()->can('forms.other.delete'))
<form action="{{ route('forms.other.destroy', $form->id) }}" method="POST" class="d-inline" onsubmit="return confirm('Are you sure you want to delete this form?');">
@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>
</div>
</section>
@endsection
@section('scripts')
<script>
// Initialize DataTables for each table
if ($('#dataTable-form_up_country').length) {
$('#dataTable-form_up_country').DataTable({ responsive: true });
}
if ($('#dataTable-form_vehicle_running_cost').length) {
$('#dataTable-form_vehicle_running_cost').DataTable({ responsive: true });
}
if ($('#dataTable-form_entertainment_presentation').length) {
$('#dataTable-form_entertainment_presentation').DataTable({ responsive: true });
}
if ($('#dataTable-form_meeting_seminar').length) {
$('#dataTable-form_meeting_seminar').DataTable({ responsive: true });
}
if ($('#dataTable-form_others').length) {
$('#dataTable-form_others').DataTable({ responsive: true });
}
</script>
@endsection
@@ -64,6 +64,7 @@
@endforeach
</td>
<td>
<a class="btn btn-success text-white" href="{{ route('admin.admins.expense', $admin->id) }}">View Expense</a>
@if (auth()->user()->can('admin.edit'))
<a class="btn btn-success text-white"
href="{{ route('admin.admins.edit', $admin->id) }}">Edit</a>
@@ -5,6 +5,8 @@
@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">
@@ -63,7 +65,7 @@
</div>
<div class="mb-3">
<label class="form-label">Total</label>
<input type="number" class="form-control" name="total" id="total" required value="{{ old('total') }}">
<input type="string" class="form-control" name="total" id="total" required value="{{ old('total') }}">
</div>
<div class="mb-3">
<label class="form-label">Bukti 1</label>
@@ -86,4 +88,14 @@
</div>
</div>
</section>
<script>
new AutoNumeric('#total', {
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
@@ -5,6 +5,8 @@
@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">
@@ -64,7 +66,7 @@
</div>
<div class="mb-3">
<label class="form-label">Total</label>
<input type="number" class="form-control" name="total" id="total" required value="{{ $form->total }}">
<input type="string" class="form-control" name="total" id="total" required value="{{ $form->total }}">
</div>
<div class="mb-3">
<label class="form-label">Bukti 1</label>
@@ -87,4 +89,14 @@
</div>
</div>
</section>
<script>
new AutoNumeric('#total', {
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
@@ -20,6 +20,48 @@
</div>
</div>
</section>
<section class="content">
<div class="container-fluid">
<div class="row">
<!-- Total Expense -->
<div class="col-lg-4 col-6">
<div class="small-box bg-info">
<div class="inner">
<h3>Rp {{ number_format($forms->sum('total'), 0, ',', '.') }}</h3>
<p>Total Expense</p>
</div>
<div class="icon">
<i class="fas fa-wallet"></i>
</div>
</div>
</div>
<!-- Approved Expense -->
<div class="col-lg-4 col-6">
<div class="small-box bg-success">
<div class="inner">
<h3>Rp {{ number_format($forms->whereIn('status', ['Approved', 'Closed'])->sum('total'), 0, ',', '.') }}</h3>
<p>Approved Expenses</p>
</div>
<div class="icon">
<i class="fas fa-check-circle"></i>
</div>
</div>
</div>
<!-- Pending Expense -->
<div class="col-lg-4 col-6">
<div class="small-box bg-warning">
<div class="inner">
<h3 class="text-white">Rp {{ number_format($forms->where('status', 'On Progress')->sum('total'), 0, ',', '.') }}</h3>
<p class="text-white">Pending Expenses</p>
</div>
<div class="icon">
<i class="fas fa-hourglass-half"></i>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="content">
<div class="container-fluid">
<div class="card card-primary card-outline">
@@ -47,12 +89,14 @@
<th>Keterangan</th>
<th>Total</th>
<th>Nama Penerima</th>
<th>NPWP / NIK</th>
<th>Bukti 1</th>
<th>Bukti 2</th>
<th>Bukti 3</th>
<th>Account Number</th>
<th>Status</th>
@if (auth()->user()->can('approval.approve') || auth()->user()->can('final_approval.approve'))
<th>Approval</th>
@endif
<th>Aksi</th>
</tr>
</thead>
@@ -69,7 +113,6 @@
<td>{{ $item->keterangan }}</td>
<td>{{ number_format($item->total, 0, ',', '.') }}</td>
<td>{{ $item->name }}</td>
<td>{{ $item->nik_or_npwp }}</td>
<td>
@if ($item->bukti1)
<a href="{{ NextCloudHelper::getFileUrl($item->bukti1) }}" target="_blank">
@@ -101,12 +144,67 @@
<td>
@if ($item->status == 'On Progress')
<span class="badge badge-warning text-white">{{ $item->status }}</span>
@elseif ($item->status == 'Completed')
@elseif ($item->status == 'Approved' || $item->status == 'Final Approved')
<span class="badge badge-success text-white">{{ $item->status }}</span>
@else
<span class="badge badge-danger text-white">{{ $item->status }}</span>
@endif
</td>
@if (auth()->user()->can('approval.approve'))
<td>
{{-- approve / reject button --}}
@if ($item->status == 'On Progress')
<form action="{{ route('forms.entertainment.approve', $item->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to approve this item?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-success btn-sm">
Approve
</button>
</form>
<form action="{{ route('forms.entertainment.reject', $item->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to reject this item?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-danger btn-sm">
Reject
</button>
</form>
@else
@if ($item->approved_at)
{{ \Carbon\Carbon::parse($item->approved_at)->locale('id')->isoFormat('D MMMM Y') }}
@elseif($item->rejected_at)
{{ \Carbon\Carbon::parse($item->rejected_at)->locale('id')->isoFormat('D MMMM Y') }}
@else
-
@endif
@endif
</td>
@elseif(auth()->user()->can('final_approval.approve'))
<td>
{{-- approve / reject button --}}
@if ($item->status == 'Approved' && $item->approved_at && !$item->final_approved_at)
<form action="{{ route('forms.entertainment.final-approve', $item->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to approve this item?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-success btn-sm">
Final Approve
</button>
</form>
@else
@if ($item->final_approved_at)
<form action="{{ route('forms.entertainment.open', $item->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to approve this item?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-success btn-sm">
Open
</button>
</form>
@else
-
@endif
@endif
</td>
@endif
<td>
@if (auth()->user()->can('forms.entertainment.edit'))
<a href="{{ route('forms.entertainment.edit', $item->id) }}" class="btn btn-warning btn-sm">
@@ -134,3 +232,11 @@
</div>
</section>
@endsection
@section('scripts')
<script>
if ($('#dataTable').length) {
$('#dataTable').DataTable({ responsive: true });
}
</script>
@endsection
@@ -43,10 +43,6 @@
<label class="form-label">Hotel</label>
<input type="text" class="form-control" name="hotel" id="hotel" required value="{{ old('hotel') }}">
</div>
<div class="mb-3">
<label class="form-label">Total</label>
<input type="text" class="form-control" name="total" id="total" required value="{{ old('total') }}">
</div>
</div>
<div class="col-lg-6">
@@ -97,28 +93,4 @@
unformatOnSubmit: true // Nilai asli tanpa format saat dikirimkan
});
</script>
<script>
const allowance = document.getElementById('allowance');
const transportAnkot = document.getElementById('transport_ankot');
const hotel = document.getElementById('hotel');
const total = document.getElementById('total');
// Function to calculate total
function calculateTotal() {
const allowanceValue = parseInt(allowance.value) || 0;
const transportAnkotValue = parseInt(transportAnkot.value) || 0;
const hotelValue = parseInt(hotel.value) || 0;
total.value = allowanceValue + transportAnkotValue + hotelValue;
}
// Attach event listeners
[allowance, transportAnkot, hotel].forEach(input => {
input.addEventListener('input', calculateTotal);
});
// Initial calculation on page load
calculateTotal();
</script>
@endsection
@@ -44,10 +44,6 @@
<label class="form-label">Hotel</label>
<input type="text" class="form-control" name="hotel" id="hotel" required value="{{ $form->hotel }}">
</div>
<div class="mb-3">
<label class="form-label">Total</label>
<input type="text" class="form-control" name="total" id="total" required value="{{ $form->total }}">
</div>
</div>
<div class="col-lg-6">
@@ -98,28 +94,4 @@
unformatOnSubmit: true // Nilai asli tanpa format saat dikirimkan
});
</script>
<script>
const allowance = document.getElementById('allowance');
const transportAnkot = document.getElementById('transport_ankot');
const hotel = document.getElementById('hotel');
const total = document.getElementById('total');
// Function to calculate total
function calculateTotal() {
const allowanceValue = parseInt(allowance.value) || 0;
const transportAnkotValue = parseInt(transportAnkot.value) || 0;
const hotelValue = parseInt(hotel.value) || 0;
total.value = allowanceValue + transportAnkotValue + hotelValue;
}
// Attach event listeners
[allowance, transportAnkot, hotel].forEach(input => {
input.addEventListener('input', calculateTotal);
});
// Initial calculation on page load
calculateTotal();
</script>
@endsection
@@ -20,6 +20,48 @@
</div>
</div>
</section>
<section class="content">
<div class="container-fluid">
<div class="row">
<!-- Total Expense -->
<div class="col-lg-4 col-6">
<div class="small-box bg-info">
<div class="inner">
<h3>Rp {{ number_format($forms->sum('total'), 0, ',', '.') }}</h3>
<p>Total Expense</p>
</div>
<div class="icon">
<i class="fas fa-wallet"></i>
</div>
</div>
</div>
<!-- Approved Expense -->
<div class="col-lg-4 col-6">
<div class="small-box bg-success">
<div class="inner">
<h3>Rp {{ number_format($forms->whereIn('status', ['Approved', 'Closed'])->sum('total'), 0, ',', '.') }}</h3>
<p>Approved Expenses</p>
</div>
<div class="icon">
<i class="fas fa-check-circle"></i>
</div>
</div>
</div>
<!-- Pending Expense -->
<div class="col-lg-4 col-6">
<div class="small-box bg-warning">
<div class="inner">
<h3 class="text-white">Rp {{ number_format($forms->where('status', 'On Progress')->sum('total'), 0, ',', '.') }}</h3>
<p class="text-white">Pending Expenses</p>
</div>
<div class="icon">
<i class="fas fa-hourglass-half"></i>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="content">
<div class="container-fluid">
<div class="card card-primary card-outline">
@@ -52,6 +94,9 @@
<th>Bukti 3</th>
<th>Account Number</th>
<th>Status</th>
@if (auth()->user()->can('approval.approve') || auth()->user()->can('final_approval.approve'))
<th>Approval</th>
@endif
<th>Aksi</th>
</tr>
</thead>
@@ -99,12 +144,67 @@
<td>
@if ($item->status == 'On Progress')
<span class="badge badge-warning text-white">{{ $item->status }}</span>
@elseif ($item->status == 'Completed')
@elseif ($item->status == 'Approved' || $item->status == 'Final Approved')
<span class="badge badge-success text-white">{{ $item->status }}</span>
@else
<span class="badge badge-danger text-white">{{ $item->status }}</span>
@endif
</td>
@if (auth()->user()->can('approval.approve'))
<td>
{{-- approve / reject button --}}
@if ($item->status == 'On Progress')
<form action="{{ route('forms.meeting.approve', $item->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to approve this item?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-success btn-sm">
Approve
</button>
</form>
<form action="{{ route('forms.meeting.reject', $item->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to reject this item?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-danger btn-sm">
Reject
</button>
</form>
@else
@if ($item->approved_at)
{{ \Carbon\Carbon::parse($item->approved_at)->locale('id')->isoFormat('D MMMM Y') }}
@elseif($item->rejected_at)
{{ \Carbon\Carbon::parse($item->rejected_at)->locale('id')->isoFormat('D MMMM Y') }}
@else
-
@endif
@endif
</td>
@elseif(auth()->user()->can('final_approval.approve'))
<td>
{{-- approve / reject button --}}
@if ($item->status == 'Approved' && $item->approved_at && !$item->final_approved_at)
<form action="{{ route('forms.meeting.final-approve', $item->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to approve this item?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-success btn-sm">
Final Approve
</button>
</form>
@else
@if ($item->final_approved_at)
<form action="{{ route('forms.meeting.open', $item->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to approve this item?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-success btn-sm">
Open
</button>
</form>
@else
-
@endif
@endif
</td>
@endif
<td>
@if (auth()->user()->can('forms.meeting.edit'))
<a href="{{ route('forms.meeting.edit', $item->id) }}" class="btn btn-warning btn-sm">
@@ -132,3 +232,11 @@
</div>
</section>
@endsection
@section('scripts')
<script>
if ($('#dataTable').length) {
$('#dataTable').DataTable({ responsive: true });
}
</script>
@endsection
@@ -0,0 +1,91 @@
@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>Tambahkan Expense Other Baru</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('forms.other.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">Kategori</label>
<select class="form-control" name="kategori_id" id="kategori_id" required>
<option value="">Pilih Kategori</option>
@foreach ($kategori as $item)
<option value="{{ $item->id }}" {{ old('kategori_id') == $item->id ? 'selected' : '' }}>
{{ $item->name }}
</option>
@endforeach
</select>
</div>
<div class="mb-3">
<label class="form-label">Tanggal</label>
<input type="date" class="form-control" name="tanggal" id="tanggal" required value="{{ old('tanggal') }}">
</div>
<div class="mb-3">
<label class="form-label">Total</label>
<input type="string" class="form-control" name="total" id="total" required value="{{ old('total') }}">
</div>
<div class="mb-3">
<label class="form-label">Keterangan</label>
<textarea class="form-control" name="keterangan" id="keterangan" required>{{ old('keterangan') }}</textarea>
</div>
</div>
<div class="col-lg-6">
<div class="mb-3">
<label class="form-label">Bukti 1</label>
<input type="file" class="form-control" name="bukti1" value="{{ old('bukti1') }}">
</div>
<div class="mb-3">
<label class="form-label">Bukti 2</label>
<input type="file" class="form-control" name="bukti2" value="{{ old('bukti2') }}">
</div>
<div class="mb-3">
<label class="form-label">Bukti 3</label>
<input type="file" class="form-control" name="bukti3" value="{{ old('bukti3') }}">
</div>
</div>
<button type="submit" class="btn btn-primary ml-2">Submit</button>
</div>
</form>
</div>
</div>
</div>
</section>
<script>
new AutoNumeric('#total', {
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,92 @@
@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>Edit Expense Other</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('forms.other.update', $form->id) }}" enctype="multipart/form-data">
@csrf
@method('PUT')
@include('backend.layouts.partials.messages')
<div class="row">
<div class="col-lg-6">
<div class="mb-3">
<label class="form-label">Kategori</label>
<select class="form-control" name="kategori_id" id="kategori_id" required>
<option value="">Pilih Kategori</option>
@foreach ($kategori as $item)
<option value="{{ $item->id }}" {{ $form->kategori_id == $item->id ? 'selected' : '' }}>
{{ $item->name }}
</option>
@endforeach
</select>
</div>
<div class="mb-3">
<label class="form-label">Tanggal</label>
<input type="date" class="form-control" name="tanggal" id="tanggal" required value="{{ $form->tanggal }}">
</div>
<div class="mb-3">
<label class="form-label">Total</label>
<input type="string" class="form-control" name="total" id="total" required value="{{ $form->total }}">
</div>
<div class="mb-3">
<label class="form-label">Keterangan</label>
<textarea class="form-control" name="keterangan" id="keterangan" required>{{ $form->keterangan }}</textarea>
</div>
</div>
<div class="col-lg-6">
<div class="mb-3">
<label class="form-label">Bukti 1</label>
<input type="file" class="form-control" name="bukti1" value="{{ $form->bukti1 }}">
</div>
<div class="mb-3">
<label class="form-label">Bukti 2</label>
<input type="file" class="form-control" name="bukti2" value="{{ $form->bukti2 }}">
</div>
<div class="mb-3">
<label class="form-label">Bukti 3</label>
<input type="file" class="form-control" name="bukti3" value="{{ $form->bukti3 }}">
</div>
</div>
<button type="submit" class="btn btn-primary ml-2">Update</button>
</div>
</form>
</div>
</div>
</div>
</section>
<script>
new AutoNumeric('#total', {
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,240 @@
@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>Forms Others</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">
<!-- Total Expense -->
<div class="col-lg-4 col-6">
<div class="small-box bg-info">
<div class="inner">
<h3>Rp {{ number_format($forms->sum('total'), 0, ',', '.') }}</h3>
<p>Total Expense</p>
</div>
<div class="icon">
<i class="fas fa-wallet"></i>
</div>
</div>
</div>
<!-- Approved Expense -->
<div class="col-lg-4 col-6">
<div class="small-box bg-success">
<div class="inner">
<h3>Rp {{ number_format($forms->whereIn('status', ['Approved', 'Closed'])->sum('total'), 0, ',', '.') }}</h3>
<p>Approved Expenses</p>
</div>
<div class="icon">
<i class="fas fa-check-circle"></i>
</div>
</div>
</div>
<!-- Pending Expense -->
<div class="col-lg-4 col-6">
<div class="small-box bg-warning">
<div class="inner">
<h3 class="text-white">Rp {{ number_format($forms->where('status', 'On Progress')->sum('total'), 0, ',', '.') }}</h3>
<p class="text-white">Pending Expenses</p>
</div>
<div class="icon">
<i class="fas fa-hourglass-half"></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">List Data Forms Others Anda</h4>
<p class="float-right mb-2">
@if (auth()->user()->can('forms.other.create'))
<a class="btn btn-primary text-white" href="{{ route('forms.other.create') }}">
Add New Expense Others
</a>
@endif
</p>
<div class="clearfix"></div>
<div class="dataTables_wrapper dt-bootstrap4 mt-2">
@include('backend.layouts.partials.messages')
<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>Nama</th>
<th>Tanggal</th>
<th>Jenis</th>
<th>Keterangan</th>
<th>Total</th>
<th>Bukti 1</th>
<th>Bukti 2</th>
<th>Bukti 3</th>
<th>Account Number</th>
<th>Status</th>
@if (auth()->user()->can('approval.approve') || auth()->user()->can('final_approval.approve'))
<th>Approval</th>
@endif
<th>Aksi</th>
</tr>
</thead>
<tbody>
@php
use App\Helpers\NextCloudHelper;
@endphp
@foreach ($forms as $item)
<tr>
<td>{{ $loop->iteration }}</td>
<td>{{ $item->user->name }}</td>
<td>{{ \Carbon\Carbon::parse($item->tanggal)->locale('id')->isoFormat('D MMMM Y') }}</td>
<td>{{ $item->kategori->name }}</td>
<td>{{ $item->keterangan }}</td>
<td>{{ number_format($item->total, 0, ',', '.') }}</td>
<td>
@if ($item->bukti1)
<a href="{{ NextCloudHelper::getFileUrl($item->bukti1) }}" target="_blank">
Download
</a>
@else
-
@endif
</td>
<td>
@if ($item->bukti2)
<a href="{{ NextCloudHelper::getFileUrl($item->bukti2) }}" target="_blank">
Download
</a>
@else
-
@endif
</td>
<td>
@if ($item->bukti3)
<a href="{{ NextCloudHelper::getFileUrl($item->bukti3) }}" target="_blank">
Download
</a>
@else
-
@endif
</td>
<td>{{ $item->account_number }}</td>
<td>
@if ($item->status == 'On Progress')
<span class="badge badge-warning text-white">{{ $item->status }}</span>
@elseif ($item->status == 'Approved' || $item->status == 'Final Approved')
<span class="badge badge-success text-white">{{ $item->status }}</span>
@else
<span class="badge badge-danger text-white">{{ $item->status }}</span>
@endif
</td>
@if (auth()->user()->can('approval.approve'))
<td>
{{-- approve / reject button --}}
@if ($item->status == 'On Progress')
<form action="{{ route('forms.other.approve', $item->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to approve this item?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-success btn-sm">
Approve
</button>
</form>
<form action="{{ route('forms.other.reject', $item->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to reject this item?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-danger btn-sm">
Reject
</button>
</form>
@else
@if ($item->approved_at)
{{ \Carbon\Carbon::parse($item->approved_at)->locale('id')->isoFormat('D MMMM Y') }}
@elseif($item->rejected_at)
{{ \Carbon\Carbon::parse($item->rejected_at)->locale('id')->isoFormat('D MMMM Y') }}
@else
-
@endif
@endif
</td>
@elseif(auth()->user()->can('final_approval.approve'))
<td>
{{-- approve / reject button --}}
@if ($item->status == 'Approved' && $item->approved_at && !$item->final_approved_at)
<form action="{{ route('forms.other.final-approve', $item->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to approve this item?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-success btn-sm">
Final Approve
</button>
</form>
@else
@if ($item->final_approved_at)
<form action="{{ route('forms.other.open', $item->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to approve this item?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-success btn-sm">
Open
</button>
</form>
@else
-
@endif
@endif
</td>
@endif
<td>
@if (auth()->user()->can('forms.other.edit'))
<a href="{{ route('forms.other.edit', $item->id) }}" class="btn btn-warning btn-sm">
<i class="fas fa-edit text-white"></i>
</a>
@endif
@if (auth()->user()->can('forms.other.delete'))
<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
@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>
</section>
@endsection
@section('scripts')
<script>
if ($('#dataTable').length) {
$('#dataTable').DataTable({ responsive: true });
}
</script>
@endsection
@@ -5,6 +5,7 @@
@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">
@@ -52,26 +53,22 @@
</div>
<div class="mb-3">
<label class="form-label">Allowance</label>
<input type="number" class="form-control" name="allowance" id="allowance" required value="{{ old('allowance') }}">
<input type="string" class="form-control" name="allowance" id="allowance" required value="{{ old('allowance') }}">
</div>
<div class="mb-3">
<label class="form-label">Transport Dalam Kota</label>
<input type="number" class="form-control" name="transport_dalkot" id="transport_dalkot" required value="{{ old('transport_dalkot') }}">
<input type="string" class="form-control" name="transport_dalkot" id="transport_dalkot" required value="{{ old('transport_dalkot') }}">
</div>
</div>
<div class="col-lg-6">
<div class="mb-3">
<label class="form-label">Transport Antar Kota</label>
<input type="number" class="form-control" name="transport_ankot" id="transport_ankot" required value="{{ old('transport_ankot') }}">
<input type="string" class="form-control" name="transport_ankot" id="transport_ankot" required value="{{ old('transport_ankot') }}">
</div>
<div class="mb-3">
<label class="form-label">Hotel</label>
<input type="number" class="form-control" name="hotel" id="hotel" required value="{{ old('hotel') }}">
</div>
<div class="mb-3">
<label class="form-label">Total</label>
<input type="number" class="form-control" name="total" id="total" required value="{{ old('total') }}" readonly>
<input type="string" class="form-control" name="hotel" id="hotel" required value="{{ old('hotel') }}">
</div>
<div class="mb-3">
<label class="form-label">Bukti 1</label>
@@ -96,28 +93,36 @@
</section>
<script>
const allowance = document.getElementById('allowance');
const transportDalkot = document.getElementById('transport_dalkot');
const transportAnkot = document.getElementById('transport_ankot');
const hotel = document.getElementById('hotel');
const total = document.getElementById('total');
// Function to calculate total
function calculateTotal() {
const allowanceValue = parseInt(allowance.value) || 0;
const transportDalkotValue = parseInt(transportDalkot.value) || 0;
const transportAnkotValue = parseInt(transportAnkot.value) || 0;
const hotelValue = parseInt(hotel.value) || 0;
total.value = allowanceValue + transportDalkotValue + transportAnkotValue + hotelValue;
}
// Attach event listeners
[allowance, transportDalkot, transportAnkot, hotel].forEach(input => {
input.addEventListener('input', calculateTotal);
new AutoNumeric('#allowance', {
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
});
// Initial calculation on page load
calculateTotal();
new AutoNumeric('#transport_dalkot', {
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
});
new AutoNumeric('#transport_ankot', {
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
});
new AutoNumeric('#hotel', {
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
@@ -20,6 +20,48 @@
</div>
</div>
</section>
<section class="content">
<div class="container-fluid">
<div class="row">
<!-- Total Expense -->
<div class="col-lg-4 col-6">
<div class="small-box bg-info">
<div class="inner">
<h3>Rp {{ number_format($forms->sum('total'), 0, ',', '.') }}</h3>
<p>Total Expense</p>
</div>
<div class="icon">
<i class="fas fa-wallet"></i>
</div>
</div>
</div>
<!-- Approved Expense -->
<div class="col-lg-4 col-6">
<div class="small-box bg-success">
<div class="inner">
<h3>Rp {{ number_format($forms->whereIn('status', ['Approved', 'Closed'])->sum('total'), 0, ',', '.') }}</h3>
<p>Approved Expenses</p>
</div>
<div class="icon">
<i class="fas fa-check-circle"></i>
</div>
</div>
</div>
<!-- Pending Expense -->
<div class="col-lg-4 col-6">
<div class="small-box bg-warning">
<div class="inner">
<h3 class="text-white">Rp {{ number_format($forms->where('status', 'On Progress')->sum('total'), 0, ',', '.') }}</h3>
<p class="text-white">Pending Expenses</p>
</div>
<div class="icon">
<i class="fas fa-hourglass-half"></i>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="content">
<div class="container-fluid">
<div class="card card-primary card-outline">
@@ -46,13 +88,15 @@
<th>Tanggal</th>
<th>Tujuan</th>
<th>Jarak</th>
<th>Allowance</th>
<th>Total</th>
<th>Bukti 1</th>
<th>Bukti 2</th>
<th>Bukti 3</th>
<th>Account Number</th>
<th>Status</th>
@if (auth()->user()->can('approval.approve') || auth()->user()->can('final_approval.approve'))
<th>Approval</th>
@endif
<th>Aksi</th>
</tr>
</thead>
@@ -68,7 +112,6 @@
<td>{{ \Carbon\Carbon::parse($item->tanggal)->locale('id')->isoFormat('D MMMM Y') }}</td>
<td>{{ $item->tujuan }}</td>
<td>{{ $item->jarak }} km</td>
<td>{{ number_format($item->allowance, 0, ',', '.') }}</td>
<td>{{ number_format($item->total, 0, ',', '.') }}</td>
<td>
@if ($item->bukti1)
@@ -101,12 +144,67 @@
<td>
@if ($item->status == 'On Progress')
<span class="badge badge-warning text-white">{{ $item->status }}</span>
@elseif ($item->status == 'Completed')
@elseif ($item->status == 'Approved' || $item->status == 'Final Approved')
<span class="badge badge-success text-white">{{ $item->status }}</span>
@else
<span class="badge badge-danger text-white">{{ $item->status }}</span>
@endif
</td>
@if (auth()->user()->can('approval.approve'))
<td>
{{-- approve / reject button --}}
@if ($item->status == 'On Progress')
<form action="{{ route('forms.up-country.approve', $item->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to approve this item?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-success btn-sm">
Approve
</button>
</form>
<form action="{{ route('forms.up-country.reject', $item->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to reject this item?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-danger btn-sm">
Reject
</button>
</form>
@else
@if ($item->approved_at)
{{ \Carbon\Carbon::parse($item->approved_at)->locale('id')->isoFormat('D MMMM Y') }}
@elseif($item->rejected_at)
{{ \Carbon\Carbon::parse($item->rejected_at)->locale('id')->isoFormat('D MMMM Y') }}
@else
-
@endif
@endif
</td>
@elseif(auth()->user()->can('final_approval.approve'))
<td>
{{-- approve / reject button --}}
@if ($item->status == 'Approved' && $item->approved_at && !$item->final_approved_at)
<form action="{{ route('forms.up-country.final-approve', $item->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to approve this item?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-success btn-sm">
Final Approve
</button>
</form>
@else
@if ($item->final_approved_at)
<form action="{{ route('forms.up-country.open', $item->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to approve this item?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-success btn-sm">
Open
</button>
</form>
@else
-
@endif
@endif
</td>
@endif
<td>
@if (auth()->user()->can('forms.country.edit'))
<a href="{{ route('forms.up-country.edit', $item->id) }}" class="btn btn-warning btn-sm">
@@ -134,3 +232,11 @@
</div>
</section>
@endsection
@section('scripts')
<script>
if ($('#dataTable').length) {
$('#dataTable').DataTable({ responsive: true });
}
</script>
@endsection
@@ -5,6 +5,8 @@
@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">
@@ -38,8 +40,8 @@
<input type="text" class="form-control" name="liter" required value="{{ old('liter') }}">
</div>
<div class="mb-3">
<label class="form-label">Harga Bensin</label>
<input type="number" class="form-control" name="harga" required value="{{ old('harga') }}">
<label class="form-label">Total Harga Bensin</label>
<input type="string" class="form-control" name="total" id="total" required value="{{ old('total') }}">
</div>
<div class="mb-3">
<label class="form-label">Jarak</label>
@@ -86,4 +88,14 @@
</div>
</div>
</section>
<script>
new AutoNumeric('#total', {
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
@@ -5,6 +5,7 @@
@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">
@@ -39,8 +40,8 @@
<input type="text" class="form-control" name="liter" required value="{{ $form->liter }}">
</div>
<div class="mb-3">
<label class="form-label">Harga Bensin</label>
<input type="number" class="form-control" name="harga" required value="{{ $form->harga }}">
<label class="form-label">Total Harga Bensin</label>
<input type="string" class="form-control" name="total" id="total" required value="{{ $form->total }}">
</div>
<div class="mb-3">
<label class="form-label">Jarak</label>
@@ -85,4 +86,14 @@
</div>
</div>
</section>
<script>
new AutoNumeric('#total', {
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
@@ -20,6 +20,48 @@
</div>
</div>
</section>
<section class="content">
<div class="container-fluid">
<div class="row">
<!-- Total Expense -->
<div class="col-lg-4 col-6">
<div class="small-box bg-info">
<div class="inner">
<h3>Rp {{ number_format($forms->sum('total'), 0, ',', '.') }}</h3>
<p>Total Expense</p>
</div>
<div class="icon">
<i class="fas fa-wallet"></i>
</div>
</div>
</div>
<!-- Approved Expense -->
<div class="col-lg-4 col-6">
<div class="small-box bg-success">
<div class="inner">
<h3>Rp {{ number_format($forms->whereIn('status', ['Approved', 'Closed'])->sum('total'), 0, ',', '.') }}</h3>
<p>Approved Expenses</p>
</div>
<div class="icon">
<i class="fas fa-check-circle"></i>
</div>
</div>
</div>
<!-- Pending Expense -->
<div class="col-lg-4 col-6">
<div class="small-box bg-warning">
<div class="inner">
<h3 class="text-white">Rp {{ number_format($forms->where('status', 'On Progress')->sum('total'), 0, ',', '.') }}</h3>
<p class="text-white">Pending Expenses</p>
</div>
<div class="icon">
<i class="fas fa-hourglass-half"></i>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="content">
<div class="container-fluid">
<div class="card card-primary card-outline">
@@ -44,7 +86,7 @@
<th>Nama</th>
<th>Tanggal</th>
<th>Liter</th>
<th>Harga</th>
<th>Total</th>
<th>Jarak</th>
<th>Tipe Bensin</th>
<th>Nomor Polisi</th>
@@ -53,6 +95,9 @@
<th>Bukti 3</th>
<th>Account Number</th>
<th>Status</th>
@if (auth()->user()->can('approval.approve') || auth()->user()->can('final_approval.approve'))
<th>Approval</th>
@endif
<th>Aksi</th>
</tr>
</thead>
@@ -66,7 +111,7 @@
<td>{{ $item->user->name }}</td>
<td>{{ \Carbon\Carbon::parse($item->tanggal)->locale('id')->isoFormat('dddd, D MMMM Y HH:mm:ss') }}</td>
<td>{{ $item->liter }}</td>
<td>{{ number_format($item->harga, 0, ',', '.') }}</td>
<td>{{ number_format($item->total, 0, ',', '.') }}</td>
<td>{{ $item->jarak }}</td>
<td>{{ $item->tipe_bensin }}</td>
<td>{{ $item->nopol }}</td>
@@ -101,12 +146,67 @@
<td>
@if ($item->status == 'On Progress')
<span class="badge badge-warning text-white">{{ $item->status }}</span>
@elseif ($item->status == 'Completed')
@elseif ($item->status == 'Approved' || $item->status == 'Final Approved')
<span class="badge badge-success text-white">{{ $item->status }}</span>
@else
<span class="badge badge-danger text-white">{{ $item->status }}</span>
@endif
</td>
@if (auth()->user()->can('approval.approve'))
<td>
{{-- approve / reject button --}}
@if ($item->status == 'On Progress')
<form action="{{ route('forms.vehicle.approve', $item->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to approve this item?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-success btn-sm">
Approve
</button>
</form>
<form action="{{ route('forms.vehicle.reject', $item->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to reject this item?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-danger btn-sm">
Reject
</button>
</form>
@else
@if ($item->approved_at)
{{ \Carbon\Carbon::parse($item->approved_at)->locale('id')->isoFormat('D MMMM Y') }}
@elseif($item->rejected_at)
{{ \Carbon\Carbon::parse($item->rejected_at)->locale('id')->isoFormat('D MMMM Y') }}
@else
-
@endif
@endif
</td>
@elseif(auth()->user()->can('final_approval.approve'))
<td>
{{-- approve / reject button --}}
@if ($item->status == 'Approved' && $item->approved_at && !$item->final_approved_at)
<form action="{{ route('forms.vehicle.final-approve', $item->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to approve this item?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-success btn-sm">
Final Approve
</button>
</form>
@else
@if ($item->final_approved_at)
<form action="{{ route('forms.vehicle.open', $item->id) }}" method="POST" class="d-inline"onsubmit="return confirm('Are you sure you want to approve this item?');">
@csrf
@method('PUT')
<button type="submit" class="btn btn-success btn-sm">
Open
</button>
</form>
@else
-
@endif
@endif
</td>
@endif
<td>
@if (auth()->user()->can('forms.vehicle.edit'))
<a href="{{ route('forms.vehicle.edit', $item->id) }}" class="btn btn-warning btn-sm">
@@ -134,3 +234,11 @@
</div>
</section>
@endsection
@section('scripts')
<script>
if ($('#dataTable').length) {
$('#dataTable').DataTable({ responsive: true });
}
</script>
@endsection
+365
View File
@@ -0,0 +1,365 @@
<!doctype html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Expense Approved</title>
<style media="all" type="text/css">
/* -------------------------------------
GLOBAL RESETS
------------------------------------- */
body {
font-family: Helvetica, sans-serif;
-webkit-font-smoothing: antialiased;
font-size: 16px;
line-height: 1.3;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
}
table {
border-collapse: separate;
mso-table-lspace: 0pt;
mso-table-rspace: 0pt;
width: 100%;
}
table td {
font-family: Helvetica, sans-serif;
font-size: 16px;
vertical-align: top;
}
/* -------------------------------------
BODY & CONTAINER
------------------------------------- */
body {
background-color: #f4f5f6;
margin: 0;
padding: 0;
}
.body {
background-color: #f4f5f6;
width: 100%;
}
.container {
margin: 0 auto !important;
max-width: 600px;
padding: 0;
padding-top: 24px;
width: 600px;
}
.content {
box-sizing: border-box;
display: block;
margin: 0 auto;
max-width: 600px;
padding: 0;
}
/* -------------------------------------
HEADER, FOOTER, MAIN
------------------------------------- */
.main {
background: #ffffff;
border: 1px solid #eaebed;
border-radius: 16px;
width: 100%;
}
.wrapper {
box-sizing: border-box;
padding: 24px;
}
.footer {
clear: both;
padding-top: 24px;
text-align: center;
width: 100%;
}
.footer td,
.footer p,
.footer span,
.footer a {
color: #9a9ea6;
font-size: 16px;
text-align: center;
}
/* -------------------------------------
TYPOGRAPHY
------------------------------------- */
p {
font-family: Helvetica, sans-serif;
font-size: 16px;
font-weight: normal;
margin: 0;
margin-bottom: 16px;
}
a {
color: #0867ec;
text-decoration: underline;
}
/* -------------------------------------
BUTTONS
------------------------------------- */
.btn {
box-sizing: border-box;
min-width: 100% !important;
width: 100%;
}
.btn > tbody > tr > td {
padding-bottom: 16px;
}
.btn table {
width: auto;
}
.btn table td {
background-color: #ffffff;
border-radius: 4px;
text-align: center;
}
.btn a {
background-color: #ffffff;
border: solid 2px #0867ec;
border-radius: 4px;
box-sizing: border-box;
color: #0867ec;
cursor: pointer;
display: inline-block;
font-size: 16px;
font-weight: bold;
margin: 0;
padding: 12px 24px;
text-decoration: none;
text-transform: capitalize;
}
.btn-primary table td {
background-color: #0867ec;
}
.btn-primary a {
background-color: #0867ec;
border-color: #0867ec;
color: #ffffff;
}
@media all {
.btn-primary table td:hover {
background-color: #ec0867 !important;
}
.btn-primary a:hover {
background-color: #ec0867 !important;
border-color: #ec0867 !important;
}
}
/* -------------------------------------
OTHER STYLES THAT MIGHT BE USEFUL
------------------------------------- */
.last {
margin-bottom: 0;
}
.first {
margin-top: 0;
}
.align-center {
text-align: center;
}
.align-right {
text-align: right;
}
.align-left {
text-align: left;
}
.text-link {
color: #0867ec !important;
text-decoration: underline !important;
}
.clear {
clear: both;
}
.mt0 {
margin-top: 0;
}
.mb0 {
margin-bottom: 0;
}
.preheader {
color: transparent;
display: none;
height: 0;
max-height: 0;
max-width: 0;
opacity: 0;
overflow: hidden;
mso-hide: all;
visibility: hidden;
width: 0;
}
.powered-by a {
text-decoration: none;
}
/* -------------------------------------
RESPONSIVE AND MOBILE FRIENDLY STYLES
------------------------------------- */
@media only screen and (max-width: 640px) {
.main p,
.main td,
.main span {
font-size: 16px !important;
}
.wrapper {
padding: 8px !important;
}
.content {
padding: 0 !important;
}
.container {
padding: 0 !important;
padding-top: 8px !important;
width: 100% !important;
}
.main {
border-left-width: 0 !important;
border-radius: 0 !important;
border-right-width: 0 !important;
}
.btn table {
max-width: 100% !important;
width: 100% !important;
}
.btn a {
font-size: 16px !important;
max-width: 100% !important;
width: 100% !important;
}
}
/* -------------------------------------
PRESERVE THESE STYLES IN THE HEAD
------------------------------------- */
@media all {
.ExternalClass {
width: 100%;
}
.ExternalClass,
.ExternalClass p,
.ExternalClass span,
.ExternalClass font,
.ExternalClass td,
.ExternalClass div {
line-height: 100%;
}
.apple-link a {
color: inherit !important;
font-family: inherit !important;
font-size: inherit !important;
font-weight: inherit !important;
line-height: inherit !important;
text-decoration: none !important;
}
#MessageViewBody a {
color: inherit;
text-decoration: none;
font-size: inherit;
font-family: inherit;
font-weight: inherit;
line-height: inherit;
}
}
</style>
</head>
<body>
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="body">
<tr>
<td>&nbsp;</td>
<td class="container">
<div class="content">
<!-- START CENTERED WHITE CONTAINER -->
<span class="preheader">Expense Approved</span>
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="main">
<!-- START MAIN CONTENT AREA -->
<tr>
<td class="wrapper">
<p>Halo {{ $name }},</p>
<p>Kami ingin memberitahukan bahwa pengajuan pengeluaran dengan detail sebagai berikut telah disetujui:</p>
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td align="left">
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td>
<strong>Expense Number:</strong> {{ $expense_number }}<br>
<strong>Expense Date:</strong> {{ \Carbon\Carbon::parse($tanggal)->locale('id')->isoFormat('D MMMM Y') }}<br>
<strong>Total:</strong> Rp {{ number_format($total, 0, ',', '.') }}
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p style="margin-top: 20px;">Silahkan login ke aplikasi untuk melihat detail status pengajuan pengeluaran Anda.</p>
<p>Terima kasih.</p>
</td>
<!-- END MAIN CONTENT AREA -->
</table>
<!-- START FOOTER -->
<div class="footer">
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr>
<td class="content-block">
<span class="apple-link">&copy; PT TUNGGAL IDAMAN ABDI.</span>
</td>
</tr>
<tr>
<td class="content-block powered-by" style="margin-bottom: 20px;">
Jl. Jend. Ahmad Yani No 7, Jakarta 13230, Indonesia.
</td>
<br>
</tr>
</table>
</div>
<!-- END FOOTER -->
<!-- END CENTERED WHITE CONTAINER --></div>
</td>
<td>&nbsp;</td>
</tr>
</table>
</body>
</html>
+365
View File
@@ -0,0 +1,365 @@
<!doctype html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Expense Rejected</title>
<style media="all" type="text/css">
/* -------------------------------------
GLOBAL RESETS
------------------------------------- */
body {
font-family: Helvetica, sans-serif;
-webkit-font-smoothing: antialiased;
font-size: 16px;
line-height: 1.3;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
}
table {
border-collapse: separate;
mso-table-lspace: 0pt;
mso-table-rspace: 0pt;
width: 100%;
}
table td {
font-family: Helvetica, sans-serif;
font-size: 16px;
vertical-align: top;
}
/* -------------------------------------
BODY & CONTAINER
------------------------------------- */
body {
background-color: #f4f5f6;
margin: 0;
padding: 0;
}
.body {
background-color: #f4f5f6;
width: 100%;
}
.container {
margin: 0 auto !important;
max-width: 600px;
padding: 0;
padding-top: 24px;
width: 600px;
}
.content {
box-sizing: border-box;
display: block;
margin: 0 auto;
max-width: 600px;
padding: 0;
}
/* -------------------------------------
HEADER, FOOTER, MAIN
------------------------------------- */
.main {
background: #ffffff;
border: 1px solid #eaebed;
border-radius: 16px;
width: 100%;
}
.wrapper {
box-sizing: border-box;
padding: 24px;
}
.footer {
clear: both;
padding-top: 24px;
text-align: center;
width: 100%;
}
.footer td,
.footer p,
.footer span,
.footer a {
color: #9a9ea6;
font-size: 16px;
text-align: center;
}
/* -------------------------------------
TYPOGRAPHY
------------------------------------- */
p {
font-family: Helvetica, sans-serif;
font-size: 16px;
font-weight: normal;
margin: 0;
margin-bottom: 16px;
}
a {
color: #0867ec;
text-decoration: underline;
}
/* -------------------------------------
BUTTONS
------------------------------------- */
.btn {
box-sizing: border-box;
min-width: 100% !important;
width: 100%;
}
.btn > tbody > tr > td {
padding-bottom: 16px;
}
.btn table {
width: auto;
}
.btn table td {
background-color: #ffffff;
border-radius: 4px;
text-align: center;
}
.btn a {
background-color: #ffffff;
border: solid 2px #0867ec;
border-radius: 4px;
box-sizing: border-box;
color: #0867ec;
cursor: pointer;
display: inline-block;
font-size: 16px;
font-weight: bold;
margin: 0;
padding: 12px 24px;
text-decoration: none;
text-transform: capitalize;
}
.btn-primary table td {
background-color: #0867ec;
}
.btn-primary a {
background-color: #0867ec;
border-color: #0867ec;
color: #ffffff;
}
@media all {
.btn-primary table td:hover {
background-color: #ec0867 !important;
}
.btn-primary a:hover {
background-color: #ec0867 !important;
border-color: #ec0867 !important;
}
}
/* -------------------------------------
OTHER STYLES THAT MIGHT BE USEFUL
------------------------------------- */
.last {
margin-bottom: 0;
}
.first {
margin-top: 0;
}
.align-center {
text-align: center;
}
.align-right {
text-align: right;
}
.align-left {
text-align: left;
}
.text-link {
color: #0867ec !important;
text-decoration: underline !important;
}
.clear {
clear: both;
}
.mt0 {
margin-top: 0;
}
.mb0 {
margin-bottom: 0;
}
.preheader {
color: transparent;
display: none;
height: 0;
max-height: 0;
max-width: 0;
opacity: 0;
overflow: hidden;
mso-hide: all;
visibility: hidden;
width: 0;
}
.powered-by a {
text-decoration: none;
}
/* -------------------------------------
RESPONSIVE AND MOBILE FRIENDLY STYLES
------------------------------------- */
@media only screen and (max-width: 640px) {
.main p,
.main td,
.main span {
font-size: 16px !important;
}
.wrapper {
padding: 8px !important;
}
.content {
padding: 0 !important;
}
.container {
padding: 0 !important;
padding-top: 8px !important;
width: 100% !important;
}
.main {
border-left-width: 0 !important;
border-radius: 0 !important;
border-right-width: 0 !important;
}
.btn table {
max-width: 100% !important;
width: 100% !important;
}
.btn a {
font-size: 16px !important;
max-width: 100% !important;
width: 100% !important;
}
}
/* -------------------------------------
PRESERVE THESE STYLES IN THE HEAD
------------------------------------- */
@media all {
.ExternalClass {
width: 100%;
}
.ExternalClass,
.ExternalClass p,
.ExternalClass span,
.ExternalClass font,
.ExternalClass td,
.ExternalClass div {
line-height: 100%;
}
.apple-link a {
color: inherit !important;
font-family: inherit !important;
font-size: inherit !important;
font-weight: inherit !important;
line-height: inherit !important;
text-decoration: none !important;
}
#MessageViewBody a {
color: inherit;
text-decoration: none;
font-size: inherit;
font-family: inherit;
font-weight: inherit;
line-height: inherit;
}
}
</style>
</head>
<body>
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="body">
<tr>
<td>&nbsp;</td>
<td class="container">
<div class="content">
<!-- START CENTERED WHITE CONTAINER -->
<span class="preheader">Expense Rejected</span>
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="main">
<!-- START MAIN CONTENT AREA -->
<tr>
<td class="wrapper">
<p>Halo {{ $name }},</p>
<p>Kami ingin memberitahukan bahwa pengajuan pengeluaran dengan detail sebagai berikut telah ditolak:</p>
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td align="left">
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td>
<strong>Expense Number:</strong> {{ $expense_number }}<br>
<strong>Expense Date:</strong> {{ \Carbon\Carbon::parse($tanggal)->locale('id')->isoFormat('D MMMM Y') }}<br>
<strong>Total:</strong> Rp {{ number_format($total, 0, ',', '.') }}
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p style="margin-top: 20px;">Silahkan login ke aplikasi untuk melihat detail status pengajuan pengeluaran Anda.</p>
<p>Terima kasih.</p>
</td>
<!-- END MAIN CONTENT AREA -->
</table>
<!-- START FOOTER -->
<div class="footer">
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr>
<td class="content-block">
<span class="apple-link">&copy; PT TUNGGAL IDAMAN ABDI.</span>
</td>
</tr>
<tr>
<td class="content-block powered-by" style="margin-bottom: 20px;">
Jl. Jend. Ahmad Yani No 7, Jakarta 13230, Indonesia.
</td>
<br>
</tr>
</table>
</div>
<!-- END FOOTER -->
<!-- END CENTERED WHITE CONTAINER --></div>
</td>
<td>&nbsp;</td>
</tr>
</table>
</body>
</html>
+364
View File
@@ -0,0 +1,364 @@
<!doctype html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Expense Approved</title>
<style media="all" type="text/css">
/* -------------------------------------
GLOBAL RESETS
------------------------------------- */
body {
font-family: Helvetica, sans-serif;
-webkit-font-smoothing: antialiased;
font-size: 16px;
line-height: 1.3;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
}
table {
border-collapse: separate;
mso-table-lspace: 0pt;
mso-table-rspace: 0pt;
width: 100%;
}
table td {
font-family: Helvetica, sans-serif;
font-size: 16px;
vertical-align: top;
}
/* -------------------------------------
BODY & CONTAINER
------------------------------------- */
body {
background-color: #f4f5f6;
margin: 0;
padding: 0;
}
.body {
background-color: #f4f5f6;
width: 100%;
}
.container {
margin: 0 auto !important;
max-width: 600px;
padding: 0;
padding-top: 24px;
width: 600px;
}
.content {
box-sizing: border-box;
display: block;
margin: 0 auto;
max-width: 600px;
padding: 0;
}
/* -------------------------------------
HEADER, FOOTER, MAIN
------------------------------------- */
.main {
background: #ffffff;
border: 1px solid #eaebed;
border-radius: 16px;
width: 100%;
}
.wrapper {
box-sizing: border-box;
padding: 24px;
}
.footer {
clear: both;
padding-top: 24px;
text-align: center;
width: 100%;
}
.footer td,
.footer p,
.footer span,
.footer a {
color: #9a9ea6;
font-size: 16px;
text-align: center;
}
/* -------------------------------------
TYPOGRAPHY
------------------------------------- */
p {
font-family: Helvetica, sans-serif;
font-size: 16px;
font-weight: normal;
margin: 0;
margin-bottom: 16px;
}
a {
color: #0867ec;
text-decoration: underline;
}
/* -------------------------------------
BUTTONS
------------------------------------- */
.btn {
box-sizing: border-box;
min-width: 100% !important;
width: 100%;
}
.btn > tbody > tr > td {
padding-bottom: 16px;
}
.btn table {
width: auto;
}
.btn table td {
background-color: #ffffff;
border-radius: 4px;
text-align: center;
}
.btn a {
background-color: #ffffff;
border: solid 2px #0867ec;
border-radius: 4px;
box-sizing: border-box;
color: #0867ec;
cursor: pointer;
display: inline-block;
font-size: 16px;
font-weight: bold;
margin: 0;
padding: 12px 24px;
text-decoration: none;
text-transform: capitalize;
}
.btn-primary table td {
background-color: #0867ec;
}
.btn-primary a {
background-color: #0867ec;
border-color: #0867ec;
color: #ffffff;
}
@media all {
.btn-primary table td:hover {
background-color: #ec0867 !important;
}
.btn-primary a:hover {
background-color: #ec0867 !important;
border-color: #ec0867 !important;
}
}
/* -------------------------------------
OTHER STYLES THAT MIGHT BE USEFUL
------------------------------------- */
.last {
margin-bottom: 0;
}
.first {
margin-top: 0;
}
.align-center {
text-align: center;
}
.align-right {
text-align: right;
}
.align-left {
text-align: left;
}
.text-link {
color: #0867ec !important;
text-decoration: underline !important;
}
.clear {
clear: both;
}
.mt0 {
margin-top: 0;
}
.mb0 {
margin-bottom: 0;
}
.preheader {
color: transparent;
display: none;
height: 0;
max-height: 0;
max-width: 0;
opacity: 0;
overflow: hidden;
mso-hide: all;
visibility: hidden;
width: 0;
}
.powered-by a {
text-decoration: none;
}
/* -------------------------------------
RESPONSIVE AND MOBILE FRIENDLY STYLES
------------------------------------- */
@media only screen and (max-width: 640px) {
.main p,
.main td,
.main span {
font-size: 16px !important;
}
.wrapper {
padding: 8px !important;
}
.content {
padding: 0 !important;
}
.container {
padding: 0 !important;
padding-top: 8px !important;
width: 100% !important;
}
.main {
border-left-width: 0 !important;
border-radius: 0 !important;
border-right-width: 0 !important;
}
.btn table {
max-width: 100% !important;
width: 100% !important;
}
.btn a {
font-size: 16px !important;
max-width: 100% !important;
width: 100% !important;
}
}
/* -------------------------------------
PRESERVE THESE STYLES IN THE HEAD
------------------------------------- */
@media all {
.ExternalClass {
width: 100%;
}
.ExternalClass,
.ExternalClass p,
.ExternalClass span,
.ExternalClass font,
.ExternalClass td,
.ExternalClass div {
line-height: 100%;
}
.apple-link a {
color: inherit !important;
font-family: inherit !important;
font-size: inherit !important;
font-weight: inherit !important;
line-height: inherit !important;
text-decoration: none !important;
}
#MessageViewBody a {
color: inherit;
text-decoration: none;
font-size: inherit;
font-family: inherit;
font-weight: inherit;
line-height: inherit;
}
}
</style>
</head>
<body>
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="body">
<tr>
<td>&nbsp;</td>
<td class="container">
<div class="content">
<!-- START CENTERED WHITE CONTAINER -->
<span class="preheader">This is preheader text. Some clients will show this text as a preview.</span>
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="main">
<!-- START MAIN CONTENT AREA -->
<tr>
<td class="wrapper">
<p>Halo {{ $name }},</p>
<p>Kami ingin memberitahukan bahwa pengajuan pengeluaran dengan detail sebagai berikut telah disetujui:</p>
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td align="left">
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td>
<strong>Expense Number:</strong> {{ $expense['number'] }}<br>
<strong>Expense Date:</strong> {{ $expense['number'] }}<br>
<strong>Total:</strong> Rp {{ number_format($expense['total'], 0, ',', '.') }}
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p style="margin-top: 20px;">Silahkan login ke aplikasi untuk melihat detail status pengajuan pengeluaran Anda.</p>
<p>Terima kasih.</p>
</td>
<!-- END MAIN CONTENT AREA -->
</table>
<!-- START FOOTER -->
<div class="footer">
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr>
<td class="content-block">
<span class="apple-link">&copy; PT TUNGGAL IDAMAN ABDI.</span>
</td>
</tr>
<tr>
<td class="content-block powered-by">
Jl. Jend. Ahmad Yani No 7, Jakarta 13230, Indonesia.
</td>
</tr>
</table>
</div>
<!-- END FOOTER -->
<!-- END CENTERED WHITE CONTAINER --></div>
</td>
<td>&nbsp;</td>
</tr>
</table>
</body>
</html>
+30
View File
@@ -15,6 +15,7 @@ use App\Http\Controllers\Master\CategoryController;
use App\Http\Controllers\Forms\FormVehicleController;
use App\Http\Controllers\Forms\FormEntertainmentPresentationController;
use App\Http\Controllers\Forms\FormMeetingSeminarController;
use App\Http\Controllers\Forms\FormOtherController;
use Illuminate\Support\Facades\Storage;
use App\Helpers\NextCloudHelper;
@@ -34,6 +35,7 @@ Route::group(['prefix' => 'admin', 'as' => 'admin.'], function () {
*/
Route::group(['prefix' => 'admin', 'as' => 'admin.', 'middleware' => ['auth:admin', 'menu']], function () {
Route::resource('admins', AdminsController::class);
Route::get('/admins/expense/{user_id}', [AdminsController::class, 'expense'])->name('admins.expense');
Route::resource('roles', RolesController::class);
Route::get('/admin', [DashboardController::class, 'index'])->name('dashboard');
@@ -75,6 +77,10 @@ Route::middleware(['auth:admin', 'menu'])->group(function () {
Route::get('/up-country/edit/{id}', [FormUpCountryController::class, 'edit'])->name('forms.up-country.edit');
Route::put('/up-country/update/{id}', [FormUpCountryController::class, 'update'])->name('forms.up-country.update');
Route::delete('/up-country/destroy/{id}', [FormUpCountryController::class, 'destroy'])->name('forms.up-country.destroy');
Route::put('/up-country/approve/{id}', [FormUpCountryController::class, 'approve'])->name('forms.up-country.approve');
Route::put('/up-country/reject/{id}', [FormUpCountryController::class, 'reject'])->name('forms.up-country.reject');
Route::put('/up-country/final-approve/{id}', [FormUpCountryController::class, 'finalApprove'])->name('forms.up-country.final-approve');
Route::put('/up-country/open/{id}', [FormUpCountryController::class, 'open'])->name('forms.up-country.open');
// Vehicle Running Cost
Route::get('/vehicle-running-cost', [FormVehicleController::class, 'index'])->name('forms.vehicle');
@@ -83,6 +89,10 @@ Route::middleware(['auth:admin', 'menu'])->group(function () {
Route::get('/vehicle-running-cost/edit/{id}', [FormVehicleController::class, 'edit'])->name('forms.vehicle.edit');
Route::put('/vehicle-running-cost/update/{id}', [FormVehicleController::class, 'update'])->name('forms.vehicle.update');
Route::delete('/vehicle-running-cost/destroy/{id}', [FormVehicleController::class, 'destroy'])->name('forms.vehicle.destroy');
Route::put('/vehicle-running-cost/approve/{id}', [FormVehicleController::class, 'approve'])->name('forms.vehicle.approve');
Route::put('/vehicle-running-cost/reject/{id}', [FormVehicleController::class, 'reject'])->name('forms.vehicle.reject');
Route::put('/vehicle-running-cost/final-approve/{id}', [FormVehicleController::class, 'finalApprove'])->name('forms.vehicle.final-approve');
Route::put('/vehicle-running-cost/open/{id}', [FormVehicleController::class, 'open'])->name('forms.vehicle.open');
// Entertainment & Presentation
Route::get('/entertainment-presentation', [FormEntertainmentPresentationController::class, 'index'])->name('forms.entertainment');
@@ -91,6 +101,10 @@ Route::middleware(['auth:admin', 'menu'])->group(function () {
Route::get('/entertainment-presentation/edit/{id}', [FormEntertainmentPresentationController::class, 'edit'])->name('forms.entertainment.edit');
Route::put('/entertainment-presentation/update/{id}', [FormEntertainmentPresentationController::class, 'update'])->name('forms.entertainment.update');
Route::delete('/entertainment-presentation/destroy/{id}', [FormEntertainmentPresentationController::class, 'destroy'])->name('forms.entertainment.destroy');
Route::put('/entertainment-presentation/approve/{id}', [FormEntertainmentPresentationController::class, 'approve'])->name('forms.entertainment.approve');
Route::put('/entertainment-presentation/reject/{id}', [FormEntertainmentPresentationController::class, 'reject'])->name('forms.entertainment.reject');
Route::put('/entertainment-presentation/final-approve/{id}', [FormEntertainmentPresentationController::class, 'finalApprove'])->name('forms.entertainment.final-approve');
Route::put('/entertainment-presentation/open/{id}', [FormEntertainmentPresentationController::class, 'open'])->name('forms.entertainment.open');
// Meeting & Seminar
Route::get('/meeting-seminar', [FormMeetingSeminarController::class, 'index'])->name('forms.meeting');
@@ -99,6 +113,22 @@ Route::middleware(['auth:admin', 'menu'])->group(function () {
Route::get('/meeting-seminar/edit/{id}', [FormMeetingSeminarController::class, 'edit'])->name('forms.meeting.edit');
Route::put('/meeting-seminar/update/{id}', [FormMeetingSeminarController::class, 'update'])->name('forms.meeting.update');
Route::delete('/meeting-seminar/destroy/{id}', [FormMeetingSeminarController::class, 'destroy'])->name('forms.meeting.destroy');
Route::put('/meeting-seminar/approve/{id}', [FormMeetingSeminarController::class, 'approve'])->name('forms.meeting.approve');
Route::put('/meeting-seminar/reject/{id}', [FormMeetingSeminarController::class, 'reject'])->name('forms.meeting.reject');
Route::put('/meeting-seminar/final-approve/{id}', [FormMeetingSeminarController::class, 'finalApprove'])->name('forms.meeting.final-approve');
Route::put('/meeting-seminar/open/{id}', [FormMeetingSeminarController::class, 'open'])->name('forms.meeting.open');
// Other
Route::get('/other', [FormOtherController::class, 'index'])->name('forms.other');
Route::get('/other/create', [FormOtherController::class, 'create'])->name('forms.other.create');
Route::post('/other/store', [FormOtherController::class, 'store'])->name('forms.other.store');
Route::get('/other/edit/{id}', [FormOtherController::class, 'edit'])->name('forms.other.edit');
Route::put('/other/update/{id}', [FormOtherController::class, 'update'])->name('forms.other.update');
Route::delete('/other/destroy/{id}', [FormOtherController::class, 'destroy'])->name('forms.other.destroy');
Route::put('/other/approve/{id}', [FormOtherController::class, 'approve'])->name('forms.other.approve');
Route::put('/other/reject/{id}', [FormOtherController::class, 'reject'])->name('forms.other.reject');
Route::put('/other/final-approve/{id}', [FormOtherController::class, 'finalApprove'])->name('forms.other.final-approve');
Route::put('/other/open/{id}', [FormOtherController::class, 'open'])->name('forms.other.open');
});
//Menu Role