Initial commit: Proyek HRIS Laravel
This commit is contained in:
commit
cc98e0761e
|
|
@ -0,0 +1,18 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
indent_size = 4
|
||||||
|
indent_style = space
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
|
[*.{yml,yaml}]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[compose.yaml]
|
||||||
|
indent_size = 4
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
APP_NAME=Laravel
|
||||||
|
APP_ENV=local
|
||||||
|
APP_KEY=
|
||||||
|
APP_DEBUG=true
|
||||||
|
APP_URL=http://localhost
|
||||||
|
|
||||||
|
APP_LOCALE=en
|
||||||
|
APP_FALLBACK_LOCALE=en
|
||||||
|
APP_FAKER_LOCALE=en_US
|
||||||
|
|
||||||
|
APP_MAINTENANCE_DRIVER=file
|
||||||
|
# APP_MAINTENANCE_STORE=database
|
||||||
|
|
||||||
|
# PHP_CLI_SERVER_WORKERS=4
|
||||||
|
|
||||||
|
BCRYPT_ROUNDS=12
|
||||||
|
|
||||||
|
LOG_CHANNEL=stack
|
||||||
|
LOG_STACK=single
|
||||||
|
LOG_DEPRECATIONS_CHANNEL=null
|
||||||
|
LOG_LEVEL=debug
|
||||||
|
|
||||||
|
DB_CONNECTION=sqlite
|
||||||
|
# DB_HOST=127.0.0.1
|
||||||
|
# DB_PORT=3306
|
||||||
|
# DB_DATABASE=laravel
|
||||||
|
# DB_USERNAME=root
|
||||||
|
# DB_PASSWORD=
|
||||||
|
|
||||||
|
SESSION_DRIVER=database
|
||||||
|
SESSION_LIFETIME=120
|
||||||
|
SESSION_ENCRYPT=false
|
||||||
|
SESSION_PATH=/
|
||||||
|
SESSION_DOMAIN=null
|
||||||
|
|
||||||
|
BROADCAST_CONNECTION=log
|
||||||
|
FILESYSTEM_DISK=local
|
||||||
|
QUEUE_CONNECTION=database
|
||||||
|
|
||||||
|
CACHE_STORE=database
|
||||||
|
# CACHE_PREFIX=
|
||||||
|
|
||||||
|
MEMCACHED_HOST=127.0.0.1
|
||||||
|
|
||||||
|
REDIS_CLIENT=phpredis
|
||||||
|
REDIS_HOST=127.0.0.1
|
||||||
|
REDIS_PASSWORD=null
|
||||||
|
REDIS_PORT=6379
|
||||||
|
|
||||||
|
MAIL_MAILER=log
|
||||||
|
MAIL_SCHEME=null
|
||||||
|
MAIL_HOST=127.0.0.1
|
||||||
|
MAIL_PORT=2525
|
||||||
|
MAIL_USERNAME=null
|
||||||
|
MAIL_PASSWORD=null
|
||||||
|
MAIL_FROM_ADDRESS="hello@example.com"
|
||||||
|
MAIL_FROM_NAME="${APP_NAME}"
|
||||||
|
|
||||||
|
AWS_ACCESS_KEY_ID=
|
||||||
|
AWS_SECRET_ACCESS_KEY=
|
||||||
|
AWS_DEFAULT_REGION=us-east-1
|
||||||
|
AWS_BUCKET=
|
||||||
|
AWS_USE_PATH_STYLE_ENDPOINT=false
|
||||||
|
|
||||||
|
VITE_APP_NAME="${APP_NAME}"
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
* text=auto eol=lf
|
||||||
|
|
||||||
|
*.blade.php diff=html
|
||||||
|
*.css diff=css
|
||||||
|
*.html diff=html
|
||||||
|
*.md diff=markdown
|
||||||
|
*.php diff=php
|
||||||
|
|
||||||
|
/.github export-ignore
|
||||||
|
CHANGELOG.md export-ignore
|
||||||
|
.styleci.yml export-ignore
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
name: Issues
|
||||||
|
|
||||||
|
on:
|
||||||
|
issues:
|
||||||
|
types: [labeled]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
issues: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
help-wanted:
|
||||||
|
uses: laravel/.github/.github/workflows/issues.yml@main
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
name: Pull Requests
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request_target:
|
||||||
|
types: [opened]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
uneditable:
|
||||||
|
uses: laravel/.github/.github/workflows/pull-requests.yml@main
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
name: Tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
- '*.x'
|
||||||
|
pull_request:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * *'
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
tests:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: true
|
||||||
|
matrix:
|
||||||
|
php: [8.2, 8.3, 8.4]
|
||||||
|
|
||||||
|
name: PHP ${{ matrix.php }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
|
- name: Setup PHP
|
||||||
|
uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: ${{ matrix.php }}
|
||||||
|
extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite
|
||||||
|
coverage: none
|
||||||
|
|
||||||
|
- name: Install Composer dependencies
|
||||||
|
run: composer install --prefer-dist --no-interaction --no-progress
|
||||||
|
|
||||||
|
- name: Copy environment file
|
||||||
|
run: cp .env.example .env
|
||||||
|
|
||||||
|
- name: Generate app key
|
||||||
|
run: php artisan key:generate
|
||||||
|
|
||||||
|
- name: Execute tests
|
||||||
|
run: php artisan test
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
name: Update Changelog
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [released]
|
||||||
|
|
||||||
|
permissions: {}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
update:
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
uses: laravel/.github/.github/workflows/update-changelog.yml@main
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
*.log
|
||||||
|
.DS_Store
|
||||||
|
.env
|
||||||
|
.env.backup
|
||||||
|
.env.production
|
||||||
|
.phpactor.json
|
||||||
|
.phpunit.result.cache
|
||||||
|
/.fleet
|
||||||
|
/.idea
|
||||||
|
/.nova
|
||||||
|
/.phpunit.cache
|
||||||
|
/.vscode
|
||||||
|
/.zed
|
||||||
|
/auth.json
|
||||||
|
/node_modules
|
||||||
|
/public/build
|
||||||
|
/public/hot
|
||||||
|
/public/storage
|
||||||
|
/storage/*.key
|
||||||
|
/storage/pail
|
||||||
|
/vendor
|
||||||
|
Homestead.json
|
||||||
|
Homestead.yaml
|
||||||
|
Thumbs.db
|
||||||
|
_ide_helper.php
|
||||||
|
.phpstorm.meta.php
|
||||||
|
|
||||||
|
|
@ -0,0 +1,753 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// @formatter:off
|
||||||
|
// phpcs:ignoreFile
|
||||||
|
/**
|
||||||
|
* A helper file for your Eloquent Models
|
||||||
|
* Copy the phpDocs from this file to the correct Model,
|
||||||
|
* And remove them from this file, to prevent double declarations.
|
||||||
|
*
|
||||||
|
* @author Barry vd. Heuvel <barryvdh@gmail.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
namespace App\Models{
|
||||||
|
/**
|
||||||
|
* @property string $id_approval
|
||||||
|
* @property string $id_surat
|
||||||
|
* @property int $id_approver
|
||||||
|
* @property string|null $id_ttd_approver
|
||||||
|
* @property int $tahap 1=Manajer, 2=HRD
|
||||||
|
* @property string $status
|
||||||
|
* @property string|null $catatan
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \App\Models\User $approver
|
||||||
|
* @property-read \App\Models\SuratIzin $suratIzin
|
||||||
|
* @property-read \App\Models\TandaTangan|null $tandaTanganApprover
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ApprovalSurat newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ApprovalSurat newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ApprovalSurat query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ApprovalSurat whereCatatan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ApprovalSurat whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ApprovalSurat whereIdApproval($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ApprovalSurat whereIdApprover($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ApprovalSurat whereIdSurat($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ApprovalSurat whereIdTtdApprover($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ApprovalSurat whereStatus($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ApprovalSurat whereTahap($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ApprovalSurat whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class ApprovalSurat extends \Eloquent {}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace App\Models{
|
||||||
|
/**
|
||||||
|
* @property int $id
|
||||||
|
* @property int $id_user
|
||||||
|
* @property string|null $path_model_yml
|
||||||
|
* @property int $is_verified 0:Pending, 1:Approved, 2:Rejected
|
||||||
|
* @property string|null $last_updated
|
||||||
|
* @property string|null $encoding_wajah
|
||||||
|
* @property string $tanggal_latih
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \App\Models\User $user
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DataWajah newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DataWajah newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DataWajah query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DataWajah whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DataWajah whereEncodingWajah($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DataWajah whereId($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DataWajah whereIdUser($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DataWajah whereIsVerified($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DataWajah whereLastUpdated($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DataWajah wherePathModelYml($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DataWajah whereTanggalLatih($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DataWajah whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class DataWajah extends \Eloquent {}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace App\Models{
|
||||||
|
/**
|
||||||
|
* @property int $id
|
||||||
|
* @property string $id_penggunaan
|
||||||
|
* @property int $id_poin_sumber
|
||||||
|
* @property int $jumlah_diambil
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \App\Models\PenggunaanPoin $penggunaan
|
||||||
|
* @property-read \App\Models\PoinLembur $poinSumber
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DetailPenggunaanPoin newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DetailPenggunaanPoin newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DetailPenggunaanPoin query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DetailPenggunaanPoin whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DetailPenggunaanPoin whereId($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DetailPenggunaanPoin whereIdPenggunaan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DetailPenggunaanPoin whereIdPoinSumber($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DetailPenggunaanPoin whereJumlahDiambil($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DetailPenggunaanPoin whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class DetailPenggunaanPoin extends \Eloquent {}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace App\Models{
|
||||||
|
/**
|
||||||
|
* @property int $id_divisi
|
||||||
|
* @property string $nama_divisi
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Divisi newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Divisi newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Divisi query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Divisi whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Divisi whereIdDivisi($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Divisi whereNamaDivisi($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Divisi whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class Divisi extends \Eloquent {}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace App\Models{
|
||||||
|
/**
|
||||||
|
* @property int $id
|
||||||
|
* @property string $tanggal
|
||||||
|
* @property string $keterangan
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|HariLibur newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|HariLibur newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|HariLibur query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|HariLibur whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|HariLibur whereId($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|HariLibur whereKeterangan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|HariLibur whereTanggal($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|HariLibur whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class HariLibur extends \Eloquent {}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace App\Models{
|
||||||
|
/**
|
||||||
|
* @property int $id_jabatan
|
||||||
|
* @property string $nama_jabatan
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Jabatan newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Jabatan newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Jabatan query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Jabatan whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Jabatan whereIdJabatan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Jabatan whereNamaJabatan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Jabatan whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class Jabatan extends \Eloquent {}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace App\Models{
|
||||||
|
/**
|
||||||
|
* @property int $id_jadwal
|
||||||
|
* @property int|null $id_user
|
||||||
|
* @property string|null $tanggal
|
||||||
|
* @property int|null $id_shift
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \App\Models\PenggunaanPoin|null $penggunaanPoin
|
||||||
|
* @property-read \App\Models\ShiftKerja|null $shift
|
||||||
|
* @property-read \App\Models\User|null $user
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JadwalKerja newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JadwalKerja newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JadwalKerja query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JadwalKerja whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JadwalKerja whereIdJadwal($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JadwalKerja whereIdShift($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JadwalKerja whereIdUser($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JadwalKerja whereTanggal($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JadwalKerja whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class JadwalKerja extends \Eloquent {}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace App\Models{
|
||||||
|
/**
|
||||||
|
* @property int $id_jenis_izin
|
||||||
|
* @property string $nama_izin
|
||||||
|
* @property string|null $created_at
|
||||||
|
* @property string|null $updated_at
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisIzin newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisIzin newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisIzin query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisIzin whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisIzin whereIdJenisIzin($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisIzin whereNamaIzin($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisIzin whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class JenisIzin extends \Eloquent {}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace App\Models{
|
||||||
|
/**
|
||||||
|
* @property int $id_kompensasi
|
||||||
|
* @property string $nama_kompensasi
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisKompensasi newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisKompensasi newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisKompensasi query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisKompensasi whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisKompensasi whereIdKompensasi($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisKompensasi whereNamaKompensasi($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisKompensasi whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class JenisKompensasi extends \Eloquent {}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace App\Models{
|
||||||
|
/**
|
||||||
|
* @property int $id_pengurangan
|
||||||
|
* @property string $nama_pengurangan
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\PenggunaanPoin> $penggunaanPoin
|
||||||
|
* @property-read int|null $penggunaan_poin_count
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisPengurangan newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisPengurangan newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisPengurangan query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisPengurangan whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisPengurangan whereIdPengurangan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisPengurangan whereNamaPengurangan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisPengurangan whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class JenisPengurangan extends \Eloquent {}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace App\Models{
|
||||||
|
/**
|
||||||
|
* @property int $id_kantor
|
||||||
|
* @property string $nama_kantor
|
||||||
|
* @property string|null $alamat
|
||||||
|
* @property numeric|null $latitude
|
||||||
|
* @property numeric|null $longitude
|
||||||
|
* @property int $radius
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\User> $users
|
||||||
|
* @property-read int|null $users_count
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Kantor newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Kantor newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Kantor query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Kantor whereAlamat($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Kantor whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Kantor whereIdKantor($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Kantor whereLatitude($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Kantor whereLongitude($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Kantor whereNamaKantor($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Kantor whereRadius($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Kantor whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class Kantor extends \Eloquent {}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace App\Models{
|
||||||
|
/**
|
||||||
|
* @property string $id_lembur
|
||||||
|
* @property int|null $id_user
|
||||||
|
* @property \Illuminate\Support\Carbon $tanggal_lembur
|
||||||
|
* @property string $jam_mulai
|
||||||
|
* @property string $jam_selesai
|
||||||
|
* @property int|null $durasi_menit
|
||||||
|
* @property string|null $keterangan
|
||||||
|
* @property int|null $jumlah_poin
|
||||||
|
* @property int|null $id_kompensasi
|
||||||
|
* @property int $id_status
|
||||||
|
* @property string|null $alasan_penolakan
|
||||||
|
* @property \Illuminate\Support\Carbon $tanggal_diajukan
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \App\Models\JenisKompensasi|null $kompensasi
|
||||||
|
* @property-read \App\Models\StatusPengajuan $status
|
||||||
|
* @property-read \App\Models\User|null $user
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur whereAlasanPenolakan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur whereDurasiMenit($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur whereIdKompensasi($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur whereIdLembur($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur whereIdStatus($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur whereIdUser($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur whereJamMulai($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur whereJamSelesai($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur whereJumlahPoin($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur whereKeterangan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur whereTanggalDiajukan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur whereTanggalLembur($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class Lembur extends \Eloquent {}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace App\Models{
|
||||||
|
/**
|
||||||
|
* @property string $id_izin
|
||||||
|
* @property int|null $id_user
|
||||||
|
* @property string $tanggal_mulai
|
||||||
|
* @property string $tanggal_selesai
|
||||||
|
* @property int|null $id_jenis_izin
|
||||||
|
* @property string|null $alasan
|
||||||
|
* @property string|null $bukti_file
|
||||||
|
* @property int $id_status
|
||||||
|
* @property string|null $alasan_penolakan
|
||||||
|
* @property string $tanggal_diajukan
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \App\Models\JenisIzin|null $jenisIzin
|
||||||
|
* @property-read \App\Models\StatusPengajuan $statusPengajuan
|
||||||
|
* @property-read \App\Models\User|null $user
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PengajuanIzin newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PengajuanIzin newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PengajuanIzin query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PengajuanIzin whereAlasan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PengajuanIzin whereAlasanPenolakan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PengajuanIzin whereBuktiFile($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PengajuanIzin whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PengajuanIzin whereIdIzin($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PengajuanIzin whereIdJenisIzin($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PengajuanIzin whereIdStatus($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PengajuanIzin whereIdUser($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PengajuanIzin whereTanggalDiajukan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PengajuanIzin whereTanggalMulai($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PengajuanIzin whereTanggalSelesai($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PengajuanIzin whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class PengajuanIzin extends \Eloquent {}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace App\Models{
|
||||||
|
/**
|
||||||
|
* @property string $id_penggunaan
|
||||||
|
* @property int|null $id_user
|
||||||
|
* @property \Illuminate\Support\Carbon $tanggal_penggunaan
|
||||||
|
* @property int|null $jumlah_poin
|
||||||
|
* @property string|null $jam_masuk_custom
|
||||||
|
* @property string|null $jam_pulang_custom
|
||||||
|
* @property int|null $id_pengurangan
|
||||||
|
* @property int $id_status
|
||||||
|
* @property string|null $alasan_penolakan
|
||||||
|
* @property \Illuminate\Support\Carbon $tanggal_diajukan
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \App\Models\JenisPengurangan|null $jenisPengurangan
|
||||||
|
* @property-read \App\Models\StatusPengajuan $status
|
||||||
|
* @property-read \App\Models\User|null $user
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PenggunaanPoin newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PenggunaanPoin newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PenggunaanPoin query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PenggunaanPoin whereAlasanPenolakan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PenggunaanPoin whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PenggunaanPoin whereIdPenggunaan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PenggunaanPoin whereIdPengurangan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PenggunaanPoin whereIdStatus($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PenggunaanPoin whereIdUser($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PenggunaanPoin whereJamMasukCustom($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PenggunaanPoin whereJamPulangCustom($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PenggunaanPoin whereJumlahPoin($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PenggunaanPoin whereTanggalDiajukan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PenggunaanPoin whereTanggalPenggunaan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PenggunaanPoin whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class PenggunaanPoin extends \Eloquent {}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace App\Models{
|
||||||
|
/**
|
||||||
|
* @property int $id_pengumuman
|
||||||
|
* @property string|null $judul
|
||||||
|
* @property string|null $isi
|
||||||
|
* @property \Illuminate\Support\Carbon|null $tanggal
|
||||||
|
* @property int|null $dibuat_oleh
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \App\Models\User|null $pembuat
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Pengumuman newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Pengumuman newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Pengumuman query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Pengumuman whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Pengumuman whereDibuatOleh($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Pengumuman whereIdPengumuman($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Pengumuman whereIsi($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Pengumuman whereJudul($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Pengumuman whereTanggal($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Pengumuman whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class Pengumuman extends \Eloquent {}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace App\Models{
|
||||||
|
/**
|
||||||
|
* @property int $id_permission
|
||||||
|
* @property string $nama_permission
|
||||||
|
* @property string $slug
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Role> $roles
|
||||||
|
* @property-read int|null $roles_count
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Permission newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Permission newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Permission query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Permission whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Permission whereIdPermission($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Permission whereNamaPermission($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Permission whereSlug($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Permission whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class Permission extends \Eloquent {}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace App\Models{
|
||||||
|
/**
|
||||||
|
* @property-read \App\Models\User|null $user
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Poin newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Poin newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Poin query()
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class Poin extends \Eloquent {}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace App\Models{
|
||||||
|
/**
|
||||||
|
* @property int $id_poin
|
||||||
|
* @property int|null $id_user
|
||||||
|
* @property int|null $jumlah_poin
|
||||||
|
* @property int|null $sisa_poin
|
||||||
|
* @property string|null $id_lembur
|
||||||
|
* @property string|null $keterangan
|
||||||
|
* @property \Illuminate\Support\Carbon $tanggal
|
||||||
|
* @property \Illuminate\Support\Carbon|null $expired_at
|
||||||
|
* @property bool|null $is_fully_used
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \App\Models\Lembur|null $lembur
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PoinLembur newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PoinLembur newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PoinLembur query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PoinLembur whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PoinLembur whereExpiredAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PoinLembur whereIdLembur($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PoinLembur whereIdPoin($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PoinLembur whereIdUser($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PoinLembur whereIsFullyUsed($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PoinLembur whereJumlahPoin($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PoinLembur whereKeterangan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PoinLembur whereSisaPoin($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PoinLembur whereTanggal($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PoinLembur whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class PoinLembur extends \Eloquent {}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace App\Models{
|
||||||
|
/**
|
||||||
|
* @property int $id_presensi
|
||||||
|
* @property int|null $id_user
|
||||||
|
* @property string $tanggal
|
||||||
|
* @property string|null $jam_masuk
|
||||||
|
* @property string|null $jam_pulang
|
||||||
|
* @property numeric|null $lat_masuk
|
||||||
|
* @property numeric|null $lon_masuk
|
||||||
|
* @property numeric|null $lat_pulang
|
||||||
|
* @property numeric|null $lon_pulang
|
||||||
|
* @property string|null $foto_wajah_masuk
|
||||||
|
* @property string|null $foto_wajah_pulang
|
||||||
|
* @property int|null $id_status
|
||||||
|
* @property string|null $alasan_telat
|
||||||
|
* @property string|null $keterangan_pulang
|
||||||
|
* @property string|null $waktu_terlambat
|
||||||
|
* @property string|null $waktu_masuk_awal
|
||||||
|
* @property string|null $waktu_pulang_awal
|
||||||
|
* @property string|null $waktu_pulang_akhir
|
||||||
|
* @property int $verifikasi_wajah
|
||||||
|
* @property int $id_validasi
|
||||||
|
* @property string|null $keterangan_luar_radius
|
||||||
|
* @property string|null $alasan_penolakan
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property string|null $deleted_at
|
||||||
|
* @property-read \App\Models\User|null $user
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereAlasanPenolakan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereAlasanTelat($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereDeletedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereFotoWajahMasuk($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereFotoWajahPulang($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereIdPresensi($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereIdStatus($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereIdUser($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereIdValidasi($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereJamMasuk($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereJamPulang($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereKeteranganLuarRadius($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereKeteranganPulang($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereLatMasuk($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereLatPulang($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereLonMasuk($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereLonPulang($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereTanggal($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereUpdatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereVerifikasiWajah($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereWaktuMasukAwal($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereWaktuPulangAkhir($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereWaktuPulangAwal($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereWaktuTerlambat($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class Presensi extends \Eloquent {}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace App\Models{
|
||||||
|
/**
|
||||||
|
* @property int $id_riwayat
|
||||||
|
* @property int $id_user_1
|
||||||
|
* @property int $id_jadwal_1
|
||||||
|
* @property int $id_user_2
|
||||||
|
* @property int $id_jadwal_2
|
||||||
|
* @property string|null $keterangan
|
||||||
|
* @property int $created_by
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \App\Models\User $execAdmin
|
||||||
|
* @property-read \App\Models\JadwalKerja $jadwal1
|
||||||
|
* @property-read \App\Models\JadwalKerja $jadwal2
|
||||||
|
* @property-read \App\Models\User $user1
|
||||||
|
* @property-read \App\Models\User $user2
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|RiwayatTukarShift newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|RiwayatTukarShift newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|RiwayatTukarShift query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|RiwayatTukarShift whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|RiwayatTukarShift whereCreatedBy($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|RiwayatTukarShift whereIdJadwal1($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|RiwayatTukarShift whereIdJadwal2($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|RiwayatTukarShift whereIdRiwayat($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|RiwayatTukarShift whereIdUser1($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|RiwayatTukarShift whereIdUser2($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|RiwayatTukarShift whereKeterangan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|RiwayatTukarShift whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class RiwayatTukarShift extends \Eloquent {}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace App\Models{
|
||||||
|
/**
|
||||||
|
* @property int $id_role
|
||||||
|
* @property string $nama_role
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Permission> $permissions
|
||||||
|
* @property-read int|null $permissions_count
|
||||||
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\User> $users
|
||||||
|
* @property-read int|null $users_count
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Role newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Role newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Role query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Role whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Role whereIdRole($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Role whereNamaRole($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Role whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class Role extends \Eloquent {}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace App\Models{
|
||||||
|
/**
|
||||||
|
* @property int $id_shift
|
||||||
|
* @property string|null $nama_shift
|
||||||
|
* @property string|null $jam_mulai
|
||||||
|
* @property string|null $jam_selesai
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\JadwalKerja> $jadwalKerja
|
||||||
|
* @property-read int|null $jadwal_kerja_count
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ShiftKerja newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ShiftKerja newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ShiftKerja query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ShiftKerja whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ShiftKerja whereIdShift($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ShiftKerja whereJamMulai($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ShiftKerja whereJamSelesai($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ShiftKerja whereNamaShift($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ShiftKerja whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class ShiftKerja extends \Eloquent {}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace App\Models{
|
||||||
|
/**
|
||||||
|
* @property int $id_status
|
||||||
|
* @property string $nama_status
|
||||||
|
* @property string|null $created_at
|
||||||
|
* @property string|null $updated_at
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|StatusPengajuan newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|StatusPengajuan newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|StatusPengajuan query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|StatusPengajuan whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|StatusPengajuan whereIdStatus($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|StatusPengajuan whereNamaStatus($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|StatusPengajuan whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class StatusPengajuan extends \Eloquent {}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace App\Models{
|
||||||
|
/**
|
||||||
|
* @property string $id_surat
|
||||||
|
* @property string $id_izin
|
||||||
|
* @property int $id_user
|
||||||
|
* @property string $nomor_surat
|
||||||
|
* @property string $isi_surat
|
||||||
|
* @property string|null $id_ttd_pengaju
|
||||||
|
* @property string $status_surat
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \App\Models\ApprovalSurat|null $approvalHrd
|
||||||
|
* @property-read \App\Models\ApprovalSurat|null $approvalManajer
|
||||||
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\ApprovalSurat> $approvals
|
||||||
|
* @property-read int|null $approvals_count
|
||||||
|
* @property-read \App\Models\PengajuanIzin $pengajuanIzin
|
||||||
|
* @property-read \App\Models\TandaTangan|null $tandaTanganPengaju
|
||||||
|
* @property-read \App\Models\User $user
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|SuratIzin newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|SuratIzin newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|SuratIzin query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|SuratIzin whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|SuratIzin whereIdIzin($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|SuratIzin whereIdSurat($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|SuratIzin whereIdTtdPengaju($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|SuratIzin whereIdUser($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|SuratIzin whereIsiSurat($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|SuratIzin whereNomorSurat($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|SuratIzin whereStatusSurat($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|SuratIzin whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class SuratIzin extends \Eloquent {}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace App\Models{
|
||||||
|
/**
|
||||||
|
* @property string $id_tanda_tangan
|
||||||
|
* @property int $id_user
|
||||||
|
* @property string $file_ttd
|
||||||
|
* @property int $is_active
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \App\Models\User $user
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|TandaTangan active()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|TandaTangan newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|TandaTangan newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|TandaTangan query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|TandaTangan whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|TandaTangan whereFileTtd($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|TandaTangan whereIdTandaTangan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|TandaTangan whereIdUser($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|TandaTangan whereIsActive($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|TandaTangan whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class TandaTangan extends \Eloquent {}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace App\Models{
|
||||||
|
/**
|
||||||
|
* @property int $id
|
||||||
|
* @property string|null $nik
|
||||||
|
* @property string $nama_lengkap
|
||||||
|
* @property string $email
|
||||||
|
* @property string|null $no_telp
|
||||||
|
* @property string|null $alamat
|
||||||
|
* @property string|null $email_verified_at
|
||||||
|
* @property string $password
|
||||||
|
* @property int $sisa_cuti
|
||||||
|
* @property string|null $foto
|
||||||
|
* @property string|null $remember_token
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property int|null $id_kantor
|
||||||
|
* @property int|null $id_divisi
|
||||||
|
* @property int|null $id_jabatan
|
||||||
|
* @property int $status_aktif
|
||||||
|
* @property string|null $tgl_bergabung
|
||||||
|
* @property int $is_face_registered
|
||||||
|
* @property \Illuminate\Support\Carbon|null $deleted_at
|
||||||
|
* @property-read \App\Models\DataWajah|null $dataWajah
|
||||||
|
* @property-read \App\Models\Divisi|null $divisi
|
||||||
|
* @property-read \App\Models\Jabatan|null $jabatan
|
||||||
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\JadwalKerja> $jadwalKerja
|
||||||
|
* @property-read int|null $jadwal_kerja_count
|
||||||
|
* @property-read \App\Models\Kantor|null $kantor
|
||||||
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Lembur> $lemburs
|
||||||
|
* @property-read int|null $lemburs_count
|
||||||
|
* @property-read \Illuminate\Notifications\DatabaseNotificationCollection<int, \Illuminate\Notifications\DatabaseNotification> $notifications
|
||||||
|
* @property-read int|null $notifications_count
|
||||||
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Role> $roles
|
||||||
|
* @property-read int|null $roles_count
|
||||||
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, \Laravel\Sanctum\PersonalAccessToken> $tokens
|
||||||
|
* @property-read int|null $tokens_count
|
||||||
|
* @method static \Database\Factories\UserFactory factory($count = null, $state = [])
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|User newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|User newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|User onlyTrashed()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|User query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereAlamat($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereDeletedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereEmail($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereEmailVerifiedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereFoto($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereId($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereIdDivisi($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereIdJabatan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereIdKantor($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereIsFaceRegistered($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereNamaLengkap($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereNik($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereNoTelp($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|User wherePassword($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereRememberToken($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereSisaCuti($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereStatusAktif($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereTglBergabung($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|User whereUpdatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|User withTrashed(bool $withTrashed = true)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|User withoutTrashed()
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class User extends \Eloquent {}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
|
||||||
|
class AccrueAnnualLeave extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'app:accrue-annual-leave';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Increment annual leave (sisa_cuti) for all active employees';
|
||||||
|
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$this->info('Starting annual leave accrual process...');
|
||||||
|
|
||||||
|
$activeUsers = \App\Models\User::where('status_aktif', '=', 1)->get();
|
||||||
|
$count = 0;
|
||||||
|
|
||||||
|
foreach ($activeUsers as $user) {
|
||||||
|
|
||||||
|
$user->increment('sisa_cuti', 12);
|
||||||
|
$count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->success("Successfully accrued leave for {$count} active employees.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Models\Presensi;
|
||||||
|
use App\Models\JadwalKerja;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
|
class AutoPresensiJob extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Nama dan signature dari perintah console.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'presensi:auto-alpha';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Otomatis set Alpha untuk pegawai yang tidak absen & hapus foto lama';
|
||||||
|
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$hariIni = Carbon::today()->format('Y-m-d');
|
||||||
|
|
||||||
|
$usersWithJadwal = JadwalKerja::where('tanggal', $hariIni)
|
||||||
|
->with('user')
|
||||||
|
->get()
|
||||||
|
->pluck('id_user');
|
||||||
|
|
||||||
|
$usersPresensi = Presensi::where('tanggal', $hariIni)->pluck('id_user');
|
||||||
|
|
||||||
|
$usersAlpha = $usersWithJadwal->diff($usersPresensi);
|
||||||
|
|
||||||
|
$idAlpha = DB::table('status_presensi')->where('nama_status', 'Alpha')->value('id_status') ?? 0;
|
||||||
|
|
||||||
|
foreach ($usersAlpha as $userId) {
|
||||||
|
Presensi::create([
|
||||||
|
'id_user' => $userId,
|
||||||
|
'tanggal' => $hariIni,
|
||||||
|
'id_status' => $idAlpha,
|
||||||
|
'id_validasi' => 1,
|
||||||
|
'alasan_telat' => 'Auto Alpha by System'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->info('Auto Alpha processed for ' . $usersAlpha->count() . ' users.');
|
||||||
|
|
||||||
|
$dateLimit = Carbon::now()->subMonths(3);
|
||||||
|
|
||||||
|
$oldPresensi = Presensi::where('tanggal', '<', $dateLimit)->get();
|
||||||
|
|
||||||
|
$countDeleted = 0;
|
||||||
|
foreach ($oldPresensi as $p) {
|
||||||
|
|
||||||
|
if ($p->foto_wajah_masuk && Storage::disk('public')->exists($p->foto_wajah_masuk)) {
|
||||||
|
Storage::disk('public')->delete($p->foto_wajah_masuk);
|
||||||
|
$p->foto_wajah_masuk = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($p->foto_wajah_pulang && Storage::disk('public')->exists($p->foto_wajah_pulang)) {
|
||||||
|
Storage::disk('public')->delete($p->foto_wajah_pulang);
|
||||||
|
$p->foto_wajah_pulang = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$p->save();
|
||||||
|
$countDeleted++;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->info("Cleanup photos completed. Processed $countDeleted records.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Exports;
|
||||||
|
|
||||||
|
use Maatwebsite\Excel\Concerns\FromCollection;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithHeadings;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithMapping;
|
||||||
|
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithStyles;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||||
|
|
||||||
|
class LaporanLemburExport implements FromCollection, WithHeadings, WithMapping, ShouldAutoSize, WithStyles
|
||||||
|
{
|
||||||
|
protected $pegawai;
|
||||||
|
protected $rekap;
|
||||||
|
protected $bulan;
|
||||||
|
protected $tahun;
|
||||||
|
|
||||||
|
public function __construct($pegawai, array $rekap, $bulan, $tahun)
|
||||||
|
{
|
||||||
|
$this->pegawai = $pegawai;
|
||||||
|
$this->rekap = $rekap;
|
||||||
|
$this->bulan = $bulan;
|
||||||
|
$this->tahun = $tahun;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function collection()
|
||||||
|
{
|
||||||
|
return collect($this->pegawai);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function headings(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['LAPORAN REKAPITULASI LEMBUR PEGAWAI'],
|
||||||
|
['Periode: ' . \Carbon\Carbon::create()->month($this->bulan)->translatedFormat('F') . ' ' . $this->tahun],
|
||||||
|
[],
|
||||||
|
[
|
||||||
|
'No',
|
||||||
|
'NIK',
|
||||||
|
'Nama Lengkap',
|
||||||
|
'Divisi / Dept',
|
||||||
|
'Jabatan',
|
||||||
|
'Jumlah Hari Lembur',
|
||||||
|
'Total Waktu (Menit)',
|
||||||
|
'Durasi Jam',
|
||||||
|
'Poin Lembur Diperoleh'
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function map($row): array
|
||||||
|
{
|
||||||
|
static $no = 0;
|
||||||
|
$no++;
|
||||||
|
|
||||||
|
$dataRekap = $this->rekap[$row->id] ?? [
|
||||||
|
'total_menit' => 0,
|
||||||
|
'format_jam' => '0j 0m',
|
||||||
|
'jumlah_hari' => 0,
|
||||||
|
'poin_diperoleh' => 0,
|
||||||
|
];
|
||||||
|
|
||||||
|
return [
|
||||||
|
$no,
|
||||||
|
$row->nik ?? '-',
|
||||||
|
$row->nama_lengkap,
|
||||||
|
$row->divisi->nama_divisi ?? '-',
|
||||||
|
$row->jabatan->nama_jabatan ?? '-',
|
||||||
|
$dataRekap['jumlah_hari'] . ' Hari',
|
||||||
|
$dataRekap['total_menit'] . ' Menit',
|
||||||
|
$dataRekap['format_jam'],
|
||||||
|
$dataRekap['poin_diperoleh'] . ' Poin'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function styles(Worksheet $sheet)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
|
||||||
|
1 => ['font' => ['bold' => true, 'size' => 14]],
|
||||||
|
2 => ['font' => ['italic' => true]],
|
||||||
|
4 => ['font' => ['bold' => true], 'fill' => ['fillType' => 'solid', 'color' => ['rgb' => 'E6F4EA']]],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Exports;
|
||||||
|
|
||||||
|
use Maatwebsite\Excel\Concerns\FromCollection;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithHeadings;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithMapping;
|
||||||
|
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
|
||||||
|
use Maatwebsite\Excel\Concerns\WithStyles;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||||
|
|
||||||
|
class LaporanPresensiExport implements FromCollection, WithHeadings, WithMapping, ShouldAutoSize, WithStyles
|
||||||
|
{
|
||||||
|
protected $rekap;
|
||||||
|
protected $bulan;
|
||||||
|
protected $tahun;
|
||||||
|
|
||||||
|
public function __construct(array $rekap, $bulan, $tahun)
|
||||||
|
{
|
||||||
|
$this->rekap = $rekap;
|
||||||
|
$this->bulan = $bulan;
|
||||||
|
$this->tahun = $tahun;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function collection()
|
||||||
|
{
|
||||||
|
return collect($this->rekap);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function headings(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['LAPORAN REKAPITULASI PRESENSI PEGAWAI'],
|
||||||
|
['Periode: ' . \Carbon\Carbon::createFromDate($this->tahun, (int) $this->bulan, 1)->translatedFormat('F') . ' ' . $this->tahun],
|
||||||
|
[],
|
||||||
|
[
|
||||||
|
'No',
|
||||||
|
'NIK',
|
||||||
|
'Nama Lengkap',
|
||||||
|
'Jabatan',
|
||||||
|
'Divisi',
|
||||||
|
'Hadir',
|
||||||
|
'Izin / Cuti',
|
||||||
|
'Sakit',
|
||||||
|
'Alpha (Mangkir)',
|
||||||
|
'Terlambat',
|
||||||
|
'Poin Lembur Diperoleh'
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function map($row): array
|
||||||
|
{
|
||||||
|
static $no = 0;
|
||||||
|
$no++;
|
||||||
|
|
||||||
|
return [
|
||||||
|
$no,
|
||||||
|
$row['user']->nik ?? '-',
|
||||||
|
$row['user']->nama_lengkap,
|
||||||
|
$row['user']->jabatan->nama_jabatan ?? '-',
|
||||||
|
$row['user']->divisi->nama_divisi ?? '-',
|
||||||
|
$row['hadir'] . ' Hari',
|
||||||
|
$row['izin'] . ' Hari',
|
||||||
|
$row['sakit'] . ' Hari',
|
||||||
|
$row['alpha'] . ' Hari',
|
||||||
|
$row['terlambat'] . ' Kali',
|
||||||
|
$row['poin_lembur'] . ' Poin'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function styles(Worksheet $sheet)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
|
||||||
|
1 => ['font' => ['bold' => true, 'size' => 14]],
|
||||||
|
2 => ['font' => ['italic' => true]],
|
||||||
|
4 => ['font' => ['bold' => true], 'fill' => ['fillType' => 'solid', 'color' => ['rgb' => 'E2E8F0']]],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Helpers;
|
||||||
|
|
||||||
|
class ApiResponse
|
||||||
|
{
|
||||||
|
|
||||||
|
public static function success($data = null, string $message = 'Berhasil', int $code = 200)
|
||||||
|
{
|
||||||
|
return response()->json([
|
||||||
|
'success' => true,
|
||||||
|
'message' => $message,
|
||||||
|
'data' => $data,
|
||||||
|
], $code);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function error(string $message = 'Terjadi kesalahan', int $code = 400, $errors = null)
|
||||||
|
{
|
||||||
|
$response = [
|
||||||
|
'success' => false,
|
||||||
|
'message' => $message,
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($errors) {
|
||||||
|
$response['errors'] = $errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json($response, $code);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function validationError($errors, string $message = 'Validasi gagal')
|
||||||
|
{
|
||||||
|
return self::error($message, 422, $errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function notFound(string $message = 'Data tidak ditemukan')
|
||||||
|
{
|
||||||
|
return self::error($message, 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function unauthorized(string $message = 'Tidak memiliki akses')
|
||||||
|
{
|
||||||
|
return self::error($message, 401);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,148 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Helpers\ApiResponse;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
|
||||||
|
class AuthController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @OA\Post(
|
||||||
|
* path="/api/login",
|
||||||
|
* tags={"Authentication"},
|
||||||
|
* summary="User login",
|
||||||
|
* description="Login user and return token",
|
||||||
|
* @OA\RequestBody(
|
||||||
|
* required=true,
|
||||||
|
* @OA\JsonContent(
|
||||||
|
* required={"email","password"},
|
||||||
|
* @OA\Property(property="email", type="string", format="email", example="pegawai@mpg.com"),
|
||||||
|
* @OA\Property(property="password", type="string", format="password", example="password")
|
||||||
|
* )
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response=200,
|
||||||
|
* description="Login successful",
|
||||||
|
* @OA\JsonContent(
|
||||||
|
* @OA\Property(property="success", type="boolean", example=true),
|
||||||
|
* @OA\Property(property="message", type="string", example="Login berhasil"),
|
||||||
|
* @OA\Property(property="data", type="object",
|
||||||
|
* @OA\Property(property="token", type="string"),
|
||||||
|
* @OA\Property(property="user", type="object")
|
||||||
|
* )
|
||||||
|
* )
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response=401,
|
||||||
|
* description="Unauthorized",
|
||||||
|
* @OA\JsonContent(
|
||||||
|
* @OA\Property(property="success", type="boolean", example=false),
|
||||||
|
* @OA\Property(property="message", type="string", example="Email atau Password salah")
|
||||||
|
* )
|
||||||
|
* )
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
public function login(Request $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$validate = Validator::make($request->all(), [
|
||||||
|
'email' => 'required|email',
|
||||||
|
'password' => 'required',
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($validate->fails()) {
|
||||||
|
return ApiResponse::validationError($validate->errors());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Auth::attempt($request->only('email', 'password'))) {
|
||||||
|
return ApiResponse::unauthorized('Email atau Password salah');
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = User::where('email', $request->email)
|
||||||
|
->with(['divisi', 'jabatan', 'kantor', 'roles'])
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if ($user->status_aktif != 1) {
|
||||||
|
return ApiResponse::error('Akun Anda dinonaktifkan. Hubungi admin.', 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
$token = $user->createToken('auth_token')->plainTextToken;
|
||||||
|
|
||||||
|
return ApiResponse::success([
|
||||||
|
'token' => $token,
|
||||||
|
'user' => $user
|
||||||
|
], 'Login berhasil');
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
\Illuminate\Support\Facades\Log::error('Login Error: ' . $e->getMessage());
|
||||||
|
return ApiResponse::error('Terjadi kesalahan server: ' . $e->getMessage(), 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function logout(Request $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
/** @var \Laravel\Sanctum\PersonalAccessToken $token */
|
||||||
|
$token = $request->user()->currentAccessToken();
|
||||||
|
$token->delete();
|
||||||
|
return ApiResponse::success(null, 'Logout berhasil');
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return ApiResponse::error('Gagal logout: ' . $e->getMessage(), 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function updateProfile(Request $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$user = $request->user();
|
||||||
|
|
||||||
|
$validate = Validator::make($request->all(), [
|
||||||
|
'nama_lengkap' => 'required|string|max:255',
|
||||||
|
'no_telp' => 'nullable|string|max:15',
|
||||||
|
'password' => 'nullable|min:6',
|
||||||
|
'foto' => 'nullable|image|mimes:jpeg,png,jpg|max:2048',
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($validate->fails()) {
|
||||||
|
return ApiResponse::validationError($validate->errors());
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'nama_lengkap' => $request->nama_lengkap,
|
||||||
|
'no_telp' => $request->no_telp,
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($request->filled('password')) {
|
||||||
|
$data['password'] = Hash::make($request->password);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->hasFile('foto')) {
|
||||||
|
|
||||||
|
if ($user->foto) {
|
||||||
|
Storage::disk('public')->delete($user->foto);
|
||||||
|
}
|
||||||
|
$data['foto'] = $request->file('foto')->store('foto-profil', 'public');
|
||||||
|
}
|
||||||
|
|
||||||
|
$user->update($data);
|
||||||
|
|
||||||
|
return ApiResponse::success($user, 'Profil berhasil diperbarui');
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return ApiResponse::error('Gagal update profil: ' . $e->getMessage(), 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function user(Request $request)
|
||||||
|
{
|
||||||
|
$user = $request->user()->load(['roles', 'divisi', 'jabatan', 'kantor']);
|
||||||
|
return ApiResponse::success($user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,141 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Helpers\ApiResponse;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\JadwalKerja;
|
||||||
|
use App\Models\Presensi;
|
||||||
|
use App\Models\PenggunaanPoin;
|
||||||
|
use App\Services\PoinService;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
|
||||||
|
class DashboardController extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$user = Auth::user()->load(['divisi', 'jabatan', 'kantor']);
|
||||||
|
|
||||||
|
$today = Carbon::now('Asia/Jakarta')->toDateString();
|
||||||
|
|
||||||
|
$jadwal = JadwalKerja::with(['shift'])
|
||||||
|
->where('id_user', $user->id)
|
||||||
|
->where('tanggal', $today)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
$presensi = Presensi::where('id_user', $user->id)
|
||||||
|
->where('tanggal', $today)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
$totalPoin = (new PoinService())->getActivePoints($user->id);
|
||||||
|
|
||||||
|
$jamMasuk = $jadwal ? $jadwal->shift->jam_mulai : '-';
|
||||||
|
$jamPulang = $jadwal ? $jadwal->shift->jam_selesai : '-';
|
||||||
|
$isAdjusted = false;
|
||||||
|
$adjustmentNote = null;
|
||||||
|
$statusJadwal = 'Normal';
|
||||||
|
|
||||||
|
if ($jadwal) {
|
||||||
|
|
||||||
|
$poinOverrides = PenggunaanPoin::where('id_user', $user->id)
|
||||||
|
->where('tanggal_penggunaan', $today)
|
||||||
|
->where('id_status', 2)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
foreach ($poinOverrides as $poin) {
|
||||||
|
|
||||||
|
if ($poin->id_pengurangan == 4 && $poin->jam_masuk_custom) {
|
||||||
|
$jamMasuk = substr($poin->jam_masuk_custom, 0, 5) . ':00';
|
||||||
|
$isAdjusted = true;
|
||||||
|
$adjustmentNote = "Datang Siang (Via Poin)";
|
||||||
|
$statusJadwal = 'Masuk Siang';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($poin->id_pengurangan == 5 && $poin->jam_pulang_custom) {
|
||||||
|
$jamPulang = substr($poin->jam_pulang_custom, 0, 5) . ':00';
|
||||||
|
$isAdjusted = true;
|
||||||
|
$adjustmentNote = $adjustmentNote ? "Masuk Siang & Pulang Cepat" : "Pulang Cepat (Via Poin)";
|
||||||
|
$statusJadwal = $statusJadwal == 'Masuk Siang' ? 'Full Custom' : 'Pulang Cepat';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$ketMasuk = 'Belum Absen';
|
||||||
|
$ketPulang = null;
|
||||||
|
|
||||||
|
if ($presensi) {
|
||||||
|
if ($presensi->waktu_terlambat) {
|
||||||
|
$ketMasuk = 'Terlambat';
|
||||||
|
} else if ($presensi->waktu_masuk_awal) {
|
||||||
|
$ketMasuk = (str_contains($statusJadwal, 'Poin')) ? 'Masuk Siang (Poin) - Datang Awal' : 'Datang Awal';
|
||||||
|
} else {
|
||||||
|
$ketMasuk = (str_contains($statusJadwal, 'Poin')) ? 'Masuk Siang (Poin)' : 'Tepat Waktu';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($presensi->jam_pulang) {
|
||||||
|
if ($presensi->waktu_pulang_awal) {
|
||||||
|
$ketPulang = 'Pulang Awal';
|
||||||
|
} else if ($presensi->waktu_pulang_akhir) {
|
||||||
|
$ketPulang = (str_contains($statusJadwal, 'Poin')) ? 'Pulang Cepat (Poin) - Lembur' : 'Lembur / Pulang Akhir';
|
||||||
|
} else {
|
||||||
|
$ketPulang = (str_contains($statusJadwal, 'Poin')) ? 'Pulang Cepat (Poin)' : 'Tepat Waktu';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$dashboardData = [
|
||||||
|
'user' => [
|
||||||
|
'id' => $user->id,
|
||||||
|
'nama_lengkap' => $user->nama_lengkap,
|
||||||
|
'email' => $user->email,
|
||||||
|
'foto' => $user->foto,
|
||||||
|
'jabatan' => $user->jabatan->nama_jabatan ?? 'N/A',
|
||||||
|
'divisi' => $user->divisi->nama_divisi ?? 'N/A',
|
||||||
|
'sisa_cuti' => (int) ($user->sisa_cuti ?? 0),
|
||||||
|
'status_aktif' => $user->status_aktif ?? 'Aktif',
|
||||||
|
],
|
||||||
|
'poin' => (int) $totalPoin,
|
||||||
|
'statistik_absensi' => [
|
||||||
|
'izin' => Presensi::where('id_user', $user->id)
|
||||||
|
->whereMonth('tanggal', now()->month)
|
||||||
|
->whereYear('tanggal', now()->year)
|
||||||
|
->where('id_status', 3)
|
||||||
|
->count(),
|
||||||
|
'alpha' => Presensi::where('id_user', $user->id)
|
||||||
|
->whereMonth('tanggal', now()->month)
|
||||||
|
->whereYear('tanggal', now()->year)
|
||||||
|
->where('id_status', 5)
|
||||||
|
->count(),
|
||||||
|
],
|
||||||
|
'jadwal_hari_ini' => $jadwal ? [
|
||||||
|
'hari' => Carbon::parse($today, 'Asia/Jakarta')->translatedFormat('l, d F Y'),
|
||||||
|
'shift' => $jadwal->shift->nama_shift ?? '-',
|
||||||
|
'jam_masuk' => $jamMasuk,
|
||||||
|
'jam_pulang' => $jamPulang,
|
||||||
|
'is_adjusted' => $isAdjusted,
|
||||||
|
'note' => $adjustmentNote,
|
||||||
|
'status_jadwal' => $statusJadwal,
|
||||||
|
'kantor_nama' => $user->kantor->nama_kantor ?? '-',
|
||||||
|
'kantor_lat' => (float) ($user->kantor->latitude ?? 0),
|
||||||
|
'kantor_lon' => (float) ($user->kantor->longitude ?? 0),
|
||||||
|
'kantor_radius' => (float) ($user->kantor->radius ?? 200),
|
||||||
|
] : null,
|
||||||
|
'presensi_hari_ini' => $presensi ? [
|
||||||
|
'jam_masuk' => $presensi->jam_masuk,
|
||||||
|
'jam_pulang' => $presensi->jam_pulang,
|
||||||
|
'status' => $presensi->id_status,
|
||||||
|
'keterangan' => $ketMasuk,
|
||||||
|
'keterangan_pulang' => $ketPulang,
|
||||||
|
] : null,
|
||||||
|
];
|
||||||
|
|
||||||
|
return ApiResponse::success($dashboardData, 'Dashboard data berhasil dimuat');
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return ApiResponse::error('Gagal memuat dashboard: ' . $e->getMessage(), 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,115 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use App\Services\FaceRecognitionService;
|
||||||
|
use App\Helpers\ApiResponse;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
|
class FaceEnrollmentController extends Controller
|
||||||
|
{
|
||||||
|
protected $faceService;
|
||||||
|
|
||||||
|
public function __construct(FaceRecognitionService $faceService)
|
||||||
|
{
|
||||||
|
$this->faceService = $faceService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function enrollFace(Request $request)
|
||||||
|
{
|
||||||
|
|
||||||
|
$validator = \Validator::make($request->all(), [
|
||||||
|
'foto_depan' => 'required|image|mimes:jpeg,png,jpg|max:5120',
|
||||||
|
'foto_kanan' => 'required|image|mimes:jpeg,png,jpg|max:5120',
|
||||||
|
'foto_kiri' => 'required|image|mimes:jpeg,png,jpg|max:5120',
|
||||||
|
'foto_bawah' => 'required|image|mimes:jpeg,png,jpg|max:5120',
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($validator->fails()) {
|
||||||
|
return response()->json([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Validasi gagal',
|
||||||
|
'errors' => $validator->errors()
|
||||||
|
], 422);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$user = $request->user();
|
||||||
|
|
||||||
|
$photos = [
|
||||||
|
'depan' => $request->file('foto_depan'),
|
||||||
|
'kanan' => $request->file('foto_kanan'),
|
||||||
|
'kiri' => $request->file('foto_kiri'),
|
||||||
|
'bawah' => $request->file('foto_bawah'),
|
||||||
|
];
|
||||||
|
|
||||||
|
$result = $this->faceService->enrollFace($user->id, $photos);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true,
|
||||||
|
'message' => $result['message'],
|
||||||
|
'data' => null
|
||||||
|
], 200);
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error('Face Enrollment Error: ' . $e->getMessage());
|
||||||
|
return response()->json([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Terjadi kesalahan sistem: ' . $e->getMessage()
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFaceStatus(Request $request)
|
||||||
|
{
|
||||||
|
$user = $request->user();
|
||||||
|
|
||||||
|
$dataWajah = \DB::table('data_wajah')->where('id_user', $user->id)->first();
|
||||||
|
|
||||||
|
$status = 'not_registered';
|
||||||
|
if ($user->is_face_registered) {
|
||||||
|
$status = 'pending';
|
||||||
|
if ($dataWajah && $dataWajah->is_verified == 1) {
|
||||||
|
$status = 'verified';
|
||||||
|
} elseif ($dataWajah && $dataWajah->is_verified == 2) {
|
||||||
|
$status = 'rejected';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true,
|
||||||
|
'data' => [
|
||||||
|
'status' => $status,
|
||||||
|
'is_registered' => (bool) $user->is_face_registered
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function verifyFace(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'foto' => 'required|image|max:5120',
|
||||||
|
]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$user = $request->user();
|
||||||
|
$file = $request->file('foto');
|
||||||
|
|
||||||
|
$result = $this->faceService->verifyFace($user->id, $file);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true,
|
||||||
|
'message' => 'Wajah terverifikasi',
|
||||||
|
'data' => $result
|
||||||
|
]);
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return response()->json([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Verifikasi Gagal: ' . $e->getMessage()
|
||||||
|
], 400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Helpers\ApiResponse;
|
||||||
|
use App\Models\JenisKompensasi;
|
||||||
|
|
||||||
|
class KompensasiController extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$kompensasi = JenisKompensasi::all();
|
||||||
|
return ApiResponse::success($kompensasi);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return ApiResponse::error('Gagal memuat jenis kompensasi: ' . $e->getMessage(), 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,120 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Helpers\ApiResponse;
|
||||||
|
use App\Services\LemburService;
|
||||||
|
use App\Http\Requests\StoreLemburRequest;
|
||||||
|
use App\Models\Lembur;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
|
class LemburController extends Controller
|
||||||
|
{
|
||||||
|
protected $lemburService;
|
||||||
|
|
||||||
|
public function __construct(LemburService $lemburService)
|
||||||
|
{
|
||||||
|
$this->lemburService = $lemburService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(StoreLemburRequest $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$user = Auth::user();
|
||||||
|
|
||||||
|
$this->lemburService->createLembur($user, $request->validated());
|
||||||
|
|
||||||
|
return ApiResponse::success(null, 'Pengajuan lembur berhasil dikirim.', 201);
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return ApiResponse::error('Gagal mengajukan lembur: ' . $e->getMessage(), 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @OA\Put(
|
||||||
|
* path="/api/lembur/{id}",
|
||||||
|
* tags={"Lembur"},
|
||||||
|
* summary="Update Overtime Request",
|
||||||
|
* security={{"bearerAuth":{}}},
|
||||||
|
* @OA\Parameter(
|
||||||
|
* name="id",
|
||||||
|
* in="path",
|
||||||
|
* required=true,
|
||||||
|
* @OA\Schema(type="integer")
|
||||||
|
* ),
|
||||||
|
* @OA\RequestBody(
|
||||||
|
* required=true,
|
||||||
|
* @OA\JsonContent(
|
||||||
|
* required={"tanggal_lembur", "jam_mulai", "jam_selesai"},
|
||||||
|
* @OA\Property(property="tanggal_lembur", type="string", format="date", example="2023-10-25"),
|
||||||
|
* @OA\Property(property="jam_mulai", type="string", format="time", example="17:00"),
|
||||||
|
* @OA\Property(property="jam_selesai", type="string", format="time", example="20:00"),
|
||||||
|
* @OA\Property(property="keterangan", type="string", example="Updated reason"),
|
||||||
|
* @OA\Property(property="id_kompensasi", type="integer", example=1)
|
||||||
|
* )
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response=200,
|
||||||
|
* description="Overtime request updated successfully",
|
||||||
|
* @OA\JsonContent(
|
||||||
|
* @OA\Property(property="success", type="boolean", example=true),
|
||||||
|
* @OA\Property(property="message", type="string", example="Pengajuan lembur berhasil diperbarui.")
|
||||||
|
* )
|
||||||
|
* )
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
public function update(\App\Http\Requests\UpdateLemburRequest $request, $id)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
|
||||||
|
$lembur = Lembur::where('id_user', Auth::id())
|
||||||
|
->where('id_lembur', $id)
|
||||||
|
->where('id_status', 1)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if (!$lembur) {
|
||||||
|
return ApiResponse::error('Data lembur tidak ditemukan atau sudah diproses.', 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
$lembur->update($request->validated());
|
||||||
|
|
||||||
|
return ApiResponse::success(null, 'Pengajuan lembur berhasil diperbarui.');
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return ApiResponse::error('Gagal memperbarui lembur: ' . $e->getMessage(), 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function history(Request $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$query = Lembur::with(['status', 'kompensasi'])
|
||||||
|
->where('id_user', Auth::id());
|
||||||
|
|
||||||
|
if ($request->has('status')) {
|
||||||
|
$statusParam = $request->get('status');
|
||||||
|
|
||||||
|
$statusId = match ($statusParam) {
|
||||||
|
'pending' => 1,
|
||||||
|
'approved' => 2,
|
||||||
|
'rejected' => 3,
|
||||||
|
default => null
|
||||||
|
};
|
||||||
|
|
||||||
|
if ($statusId) {
|
||||||
|
$query->where('id_status', $statusId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$history = $query->orderBy('created_at', 'desc')->get();
|
||||||
|
|
||||||
|
return ApiResponse::success(['data' => $history], 'Riwayat lembur berhasil dimuat');
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return ApiResponse::error('Gagal memuat riwayat lembur: ' . $e->getMessage(), 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Helpers\ApiResponse;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\Pengumuman;
|
||||||
|
|
||||||
|
class PengumumanApiController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$pengumuman = Pengumuman::with('pembuat.jabatan')
|
||||||
|
->orderBy('tanggal', 'desc')
|
||||||
|
->limit(5)
|
||||||
|
->get()
|
||||||
|
->map(function ($item) {
|
||||||
|
return [
|
||||||
|
'id' => $item->id_pengumuman,
|
||||||
|
'title' => $item->judul,
|
||||||
|
'description' => $item->isi,
|
||||||
|
'tanggal' => $item->tanggal?->format('Y-m-d'),
|
||||||
|
'jabatan' => $item->pembuat?->jabatan?->nama_jabatan ?? 'Admin',
|
||||||
|
'avatar_url' => $item->pembuat?->foto,
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
return ApiResponse::success($pengumuman, 'Pengumuman berhasil dimuat');
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return ApiResponse::error('Gagal memuat pengumuman: ' . $e->getMessage(), 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,105 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Helpers\ApiResponse;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\Poin;
|
||||||
|
use App\Models\PenggunaanPoin;
|
||||||
|
use App\Services\PoinService;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
|
||||||
|
class PoinController extends Controller
|
||||||
|
{
|
||||||
|
public function getExpiringPoints()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$userId = auth()->user()->id;
|
||||||
|
|
||||||
|
$poinService = new PoinService();
|
||||||
|
$poinExpiring = $poinService->getExpiringPoints($userId);
|
||||||
|
$activePoints = $poinService->getActivePoints($userId);
|
||||||
|
|
||||||
|
$firstExpiring = $poinExpiring->first();
|
||||||
|
$formattedExpiring = null;
|
||||||
|
|
||||||
|
if ($firstExpiring) {
|
||||||
|
$formattedExpiring = [
|
||||||
|
'poin' => (int) $firstExpiring->sisa_poin,
|
||||||
|
'tanggal_kadaluarsa' => $firstExpiring->expired_at->format('Y-m-d'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return ApiResponse::success([
|
||||||
|
'expiring_points' => $formattedExpiring,
|
||||||
|
'total_poin' => (int) $activePoints
|
||||||
|
]);
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return ApiResponse::error('Terjadi kesalahan: ' . $e->getMessage(), 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPointHistory()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$userId = auth()->user()->id;
|
||||||
|
|
||||||
|
$poinService = new PoinService();
|
||||||
|
$history = $poinService->getPointHistory($userId);
|
||||||
|
|
||||||
|
return ApiResponse::success(['history' => $history]);
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return ApiResponse::error('Terjadi kesalahan: ' . $e->getMessage(), 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function redeem(Request $request)
|
||||||
|
{
|
||||||
|
$validator = Validator::make($request->all(), [
|
||||||
|
'jumlah' => 'required|integer|min:1',
|
||||||
|
'keterangan' => 'required|string',
|
||||||
|
'id_pengurangan' => 'required|integer',
|
||||||
|
'jam_masuk_custom' => 'required_if:id_pengurangan,4|date_format:H:i|nullable',
|
||||||
|
'jam_pulang_custom' => 'required_if:id_pengurangan,5|date_format:H:i|nullable',
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($validator->fails()) {
|
||||||
|
return ApiResponse::validationError($validator->errors());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$userId = auth()->user()->id;
|
||||||
|
$jumlah = $request->jumlah;
|
||||||
|
$keterangan = $request->keterangan;
|
||||||
|
|
||||||
|
$poinService = new PoinService();
|
||||||
|
$totalPoin = $poinService->getActivePoints($userId);
|
||||||
|
|
||||||
|
if ($totalPoin < $jumlah) {
|
||||||
|
return ApiResponse::error('Saldo poin tidak mencukupi', 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
preg_match('/\[(\d{4}-\d{2}-\d{2})\]/', $keterangan, $matches);
|
||||||
|
$tanggalPenggunaan = isset($matches[1]) ? $matches[1] : now()->format('Y-m-d');
|
||||||
|
|
||||||
|
PenggunaanPoin::create([
|
||||||
|
'id_user' => $userId,
|
||||||
|
'tanggal_penggunaan' => $tanggalPenggunaan,
|
||||||
|
'jumlah_poin' => $jumlah,
|
||||||
|
'id_pengurangan' => $request->id_pengurangan,
|
||||||
|
'jam_masuk_custom' => $request->jam_masuk_custom,
|
||||||
|
'jam_pulang_custom' => $request->jam_pulang_custom,
|
||||||
|
'id_status' => 1,
|
||||||
|
'tanggal_diajukan' => now(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return ApiResponse::success(null, 'Pengajuan penukaran poin berhasil disimpan');
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return ApiResponse::error($e->getMessage(), 400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,257 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Helpers\ApiResponse;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\Presensi;
|
||||||
|
use App\Services\PresensiService;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use App\Models\PenggunaanPoin;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
|
||||||
|
class PresensiController extends Controller
|
||||||
|
{
|
||||||
|
protected $presensiService;
|
||||||
|
|
||||||
|
public function __construct(PresensiService $presensiService)
|
||||||
|
{
|
||||||
|
$this->presensiService = $presensiService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$user = Auth::user();
|
||||||
|
$today = Carbon::now('Asia/Jakarta')->toDateString();
|
||||||
|
|
||||||
|
$jadwal = \App\Models\JadwalKerja::with(['shift', 'user'])
|
||||||
|
->where('id_user', $user->id)
|
||||||
|
->where('tanggal', $today)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if (!$jadwal) {
|
||||||
|
return response()->json([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Tidak ada jadwal hari ini'
|
||||||
|
], 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
$jamMasuk = $jadwal->shift->jam_mulai;
|
||||||
|
$jamPulang = $jadwal->shift->jam_selesai;
|
||||||
|
$infoJadwal = $jadwal->shift->nama_shift;
|
||||||
|
|
||||||
|
$poinOverrides = PenggunaanPoin::where('id_user', $user->id)
|
||||||
|
->whereDate('tanggal_penggunaan', $today)
|
||||||
|
->where('id_status', 2)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
foreach ($poinOverrides as $poin) {
|
||||||
|
if ($poin->id_pengurangan == 4 && $poin->jam_masuk_custom) {
|
||||||
|
$jamMasuk = substr($poin->jam_masuk_custom, 0, 5) . ':00';
|
||||||
|
$infoJadwal .= ' (Masuk Siang)';
|
||||||
|
}
|
||||||
|
if ($poin->id_pengurangan == 5 && $poin->jam_pulang_custom) {
|
||||||
|
$jamPulang = substr($poin->jam_pulang_custom, 0, 5) . ':00';
|
||||||
|
$infoJadwal .= ' (Pulang Cepat)';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$presensi = Presensi::where('id_user', $user->id)
|
||||||
|
->where('tanggal', $today)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
$ketMasuk = 'Belum Absen';
|
||||||
|
$ketPulang = null;
|
||||||
|
|
||||||
|
if ($presensi) {
|
||||||
|
if ($presensi->waktu_terlambat) {
|
||||||
|
$ketMasuk = 'Terlambat';
|
||||||
|
} else if ($presensi->waktu_masuk_awal) {
|
||||||
|
$ketMasuk = (str_contains($infoJadwal, 'Poin')) ? 'Masuk Siang (Poin) - Datang Awal' : 'Datang Awal';
|
||||||
|
} else {
|
||||||
|
$ketMasuk = (str_contains($infoJadwal, 'Poin')) ? 'Masuk Siang (Poin)' : 'Tepat Waktu';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($presensi->jam_pulang) {
|
||||||
|
if ($presensi->waktu_pulang_awal) {
|
||||||
|
$ketPulang = 'Pulang Awal';
|
||||||
|
} else if ($presensi->waktu_pulang_akhir) {
|
||||||
|
$ketPulang = (str_contains($infoJadwal, 'Poin')) ? 'Pulang Cepat (Poin) - Lembur' : 'Lembur / Pulang Akhir';
|
||||||
|
} else {
|
||||||
|
$ketPulang = (str_contains($infoJadwal, 'Poin')) ? 'Pulang Cepat (Poin)' : 'Tepat Waktu';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true,
|
||||||
|
'data' => [
|
||||||
|
'jadwal' => [
|
||||||
|
'nama_shift' => $infoJadwal,
|
||||||
|
'jam_masuk' => $jamMasuk,
|
||||||
|
'jam_pulang' => $jamPulang,
|
||||||
|
'tanggal' => Carbon::parse($today)->translatedFormat('l, d F Y'),
|
||||||
|
],
|
||||||
|
'presensi' => [
|
||||||
|
'jam_masuk' => $presensi ? $presensi->jam_masuk : null,
|
||||||
|
'jam_pulang' => $presensi ? $presensi->jam_pulang : null,
|
||||||
|
'foto_masuk' => $presensi ? $presensi->foto_masuk : null,
|
||||||
|
'status_validasi' => $presensi ? $presensi->id_validasi : null,
|
||||||
|
'keterangan' => $presensi ? $ketMasuk : null,
|
||||||
|
'keterangan_pulang' => $presensi ? $ketPulang : null,
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$request->validate([
|
||||||
|
'latitude' => 'required|numeric',
|
||||||
|
'longitude' => 'required|numeric',
|
||||||
|
'foto' => 'required|image|max:2048',
|
||||||
|
'status' => 'required|in:masuk,pulang',
|
||||||
|
'keterangan_luar_radius' => 'nullable|string|max:500',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$user = Auth::user();
|
||||||
|
|
||||||
|
if ($request->status == 'masuk') {
|
||||||
|
$data = $this->presensiService->absenMasuk($user, $request);
|
||||||
|
return ApiResponse::success($data, 'Absen masuk berhasil');
|
||||||
|
} else {
|
||||||
|
$data = $this->presensiService->absenPulang($user, $request);
|
||||||
|
return ApiResponse::success($data, 'Absen pulang berhasil');
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$code = (int) $e->getCode();
|
||||||
|
if ($code < 100 || $code > 599)
|
||||||
|
$code = 500;
|
||||||
|
return ApiResponse::error($e->getMessage(), $code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function history(Request $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$userId = Auth::id();
|
||||||
|
$history = Presensi::where('id_user', $userId)
|
||||||
|
->latest('tanggal')
|
||||||
|
->paginate(10);
|
||||||
|
|
||||||
|
$enriched = $history->getCollection()->map(function ($item) use ($userId) {
|
||||||
|
$jadwal = \App\Models\JadwalKerja::with('shift')
|
||||||
|
->where('id_user', $userId)
|
||||||
|
->where('tanggal', $item->tanggal)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
$namaShift = $jadwal?->shift?->nama_shift ?? '-';
|
||||||
|
|
||||||
|
$statusMasuk = '-';
|
||||||
|
if ($item->jam_masuk) {
|
||||||
|
if ($item->waktu_terlambat) {
|
||||||
|
$statusMasuk = 'Terlambat';
|
||||||
|
} elseif ($item->waktu_masuk_awal) {
|
||||||
|
$statusMasuk = 'Datang Awal';
|
||||||
|
} else {
|
||||||
|
$statusMasuk = 'Tepat Waktu';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ($item->alasan_telat && str_contains($item->alasan_telat, 'Cuti')) {
|
||||||
|
$statusMasuk = 'Cuti';
|
||||||
|
} elseif ($item->id_status == 3) {
|
||||||
|
$statusMasuk = 'Izin';
|
||||||
|
} elseif ($item->id_status == 4) {
|
||||||
|
$statusMasuk = 'Sakit';
|
||||||
|
} elseif ($item->id_status != null && $item->id_status != 1 && $item->id_status != 2) {
|
||||||
|
|
||||||
|
$statusStatus = \DB::table('status_presensi')->where('id_status', $item->id_status)->value('nama_status');
|
||||||
|
if ($statusStatus) {
|
||||||
|
$statusMasuk = $statusStatus;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$statusPulang = null;
|
||||||
|
if ($item->jam_pulang) {
|
||||||
|
if ($item->waktu_pulang_awal) {
|
||||||
|
$statusPulang = 'Pulang Awal';
|
||||||
|
} elseif ($item->waktu_pulang_akhir) {
|
||||||
|
$statusPulang = 'Lembur';
|
||||||
|
} else {
|
||||||
|
$statusPulang = 'Tepat Waktu';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$totalJam = '-';
|
||||||
|
if ($item->jam_masuk && $item->jam_pulang) {
|
||||||
|
try {
|
||||||
|
$masuk = Carbon::parse($item->tanggal . ' ' . $item->jam_masuk);
|
||||||
|
$pulang = Carbon::parse($item->tanggal . ' ' . $item->jam_pulang);
|
||||||
|
$diff = $masuk->diff($pulang);
|
||||||
|
$totalJam = $diff->h . 'j ' . $diff->i . 'm';
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
$totalJam = '-';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'id_presensi' => $item->id_presensi,
|
||||||
|
'tanggal' => Carbon::parse($item->tanggal)->translatedFormat('l, d F Y'),
|
||||||
|
'tanggal_raw' => $item->tanggal,
|
||||||
|
'jam_masuk' => $item->jam_masuk,
|
||||||
|
'jam_pulang' => $item->jam_pulang,
|
||||||
|
'shift' => $namaShift,
|
||||||
|
'status_masuk' => $statusMasuk,
|
||||||
|
'status_pulang' => $statusPulang,
|
||||||
|
'total_jam' => $totalJam,
|
||||||
|
'waktu_terlambat' => $item->waktu_terlambat,
|
||||||
|
'keterangan_luar_radius' => $item->keterangan_luar_radius,
|
||||||
|
'verifikasi_wajah' => (bool) $item->verifikasi_wajah,
|
||||||
|
'status_validasi' => $item->id_validasi,
|
||||||
|
'alasan_penolakan' => $item->alasan_penolakan,
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
$history->setCollection($enriched);
|
||||||
|
|
||||||
|
return ApiResponse::success($history);
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return ApiResponse::error($e->getMessage(), 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function resubmit(Request $request, $id)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$request->validate([
|
||||||
|
'keterangan' => 'required|string|max:500',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$presensi = Presensi::where('id_presensi', $id)
|
||||||
|
->where('id_user', Auth::id())
|
||||||
|
->firstOrFail();
|
||||||
|
|
||||||
|
if ($presensi->id_validasi != 3) {
|
||||||
|
return ApiResponse::error('Hanya presensi yang ditolak yang bisa diajukan ulang.', 422);
|
||||||
|
}
|
||||||
|
|
||||||
|
$presensi->update([
|
||||||
|
'id_validasi' => 2,
|
||||||
|
'alasan_penolakan' => null,
|
||||||
|
'keterangan_luar_radius' => $request->keterangan,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return ApiResponse::success(null, 'Presensi berhasil diajukan ulang. Menunggu validasi admin.');
|
||||||
|
|
||||||
|
} catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
|
||||||
|
return ApiResponse::error('Data presensi tidak ditemukan.', 404);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return ApiResponse::error($e->getMessage(), 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Helpers\ApiResponse;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
|
class ProfileController extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
public function update(Request $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$user = Auth::user();
|
||||||
|
|
||||||
|
$request->validate([
|
||||||
|
'foto' => 'nullable|image|mimes:jpeg,png,jpg|max:2048',
|
||||||
|
'no_telp' => 'nullable|string|max:20',
|
||||||
|
'alamat' => 'nullable|string|max:500',
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($request->has('no_telp')) {
|
||||||
|
$user->no_telp = $request->no_telp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->has('alamat')) {
|
||||||
|
$user->alamat = $request->alamat;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->hasFile('foto')) {
|
||||||
|
if ($user->foto && Storage::disk('public')->exists($user->foto)) {
|
||||||
|
Storage::disk('public')->delete($user->foto);
|
||||||
|
}
|
||||||
|
|
||||||
|
$path = $request->file('foto')->store('uploads/profil', 'public');
|
||||||
|
$user->foto = $path;
|
||||||
|
}
|
||||||
|
|
||||||
|
$user->save();
|
||||||
|
|
||||||
|
return ApiResponse::success($user->load(['divisi', 'jabatan', 'kantor']), 'Profil berhasil diperbarui.');
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return ApiResponse::error('Gagal update profil: ' . $e->getMessage(), 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function password(Request $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$request->validate([
|
||||||
|
'current_password' => 'required',
|
||||||
|
'new_password' => 'required|min:8|confirmed',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$user = Auth::user();
|
||||||
|
|
||||||
|
if (!Hash::check($request->current_password, $user->password)) {
|
||||||
|
return ApiResponse::error('Password lama salah.', 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
$user->password = Hash::make($request->new_password);
|
||||||
|
$user->save();
|
||||||
|
|
||||||
|
return ApiResponse::success(null, 'Kata sandi berhasil diubah.');
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return ApiResponse::error('Gagal ubah kata sandi: ' . $e->getMessage(), 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,255 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Helpers\ApiResponse;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\JadwalKerja;
|
||||||
|
use App\Models\PenggunaanPoin;
|
||||||
|
use App\Models\Presensi;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Carbon\CarbonPeriod;
|
||||||
|
|
||||||
|
class ScheduleController extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
public function today(Request $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$user = Auth::user();
|
||||||
|
|
||||||
|
$today = Carbon::now('Asia/Jakarta')->toDateString();
|
||||||
|
|
||||||
|
$jadwal = JadwalKerja::with(['shift', 'user.kantor'])
|
||||||
|
->where('id_user', $user->id)
|
||||||
|
->where('tanggal', $today)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if (!$jadwal) {
|
||||||
|
return ApiResponse::success(null, 'Tidak ada jadwal hari ini');
|
||||||
|
}
|
||||||
|
|
||||||
|
$shift = $jadwal->shift;
|
||||||
|
$jamMasuk = $shift->jam_mulai ?? '00:00:00';
|
||||||
|
$jamPulang = $shift->jam_selesai ?? '00:00:00';
|
||||||
|
$namaShift = $shift->nama_shift ?? 'Unknown Shift';
|
||||||
|
|
||||||
|
$statusJadwal = 'Normal';
|
||||||
|
$note = null;
|
||||||
|
|
||||||
|
$poinList = PenggunaanPoin::where('id_user', $user->id)
|
||||||
|
->whereDate('tanggal_penggunaan', $today)
|
||||||
|
->where('id_status', 2)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
foreach ($poinList as $poin) {
|
||||||
|
|
||||||
|
if ($poin->id_pengurangan == 4 && $poin->jam_masuk_custom) {
|
||||||
|
$jamMasuk = substr($poin->jam_masuk_custom, 0, 5) . ':00';
|
||||||
|
$statusJadwal = 'Masuk Siang (Poin)';
|
||||||
|
$note = 'Jadwal disesuaikan poin';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($poin->id_pengurangan == 5 && $poin->jam_pulang_custom) {
|
||||||
|
$jamPulang = substr($poin->jam_pulang_custom, 0, 5) . ':00';
|
||||||
|
|
||||||
|
if ($statusJadwal != 'Normal') {
|
||||||
|
$statusJadwal = 'Full Custom (Poin)';
|
||||||
|
} else {
|
||||||
|
$statusJadwal = 'Pulang Cepat (Poin)';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ApiResponse::success([
|
||||||
|
'hari' => Carbon::parse($today, 'Asia/Jakarta')->translatedFormat('l, d F Y'),
|
||||||
|
'shift' => $namaShift,
|
||||||
|
'jam_masuk' => $jamMasuk,
|
||||||
|
'jam_pulang' => $jamPulang,
|
||||||
|
'status_jadwal' => $statusJadwal,
|
||||||
|
'note' => $note,
|
||||||
|
'kantor' => $jadwal->user->kantor->nama_kantor ?? '-',
|
||||||
|
'lokasi_kantor' => [
|
||||||
|
'lat' => $jadwal->user->kantor->latitude ?? 0,
|
||||||
|
'lon' => $jadwal->user->kantor->longitude ?? 0,
|
||||||
|
],
|
||||||
|
], 'Jadwal hari ini ditemukan');
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return ApiResponse::error('Terjadi kesalahan: ' . $e->getMessage(), 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function checkScheduleByDate(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'tanggal' => 'required|date_format:Y-m-d',
|
||||||
|
]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$user = Auth::user();
|
||||||
|
$tanggal = $request->tanggal;
|
||||||
|
|
||||||
|
$jadwal = JadwalKerja::with(['shift'])
|
||||||
|
->where('id_user', $user->id)
|
||||||
|
->where('tanggal', $tanggal)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if (!$jadwal) {
|
||||||
|
return ApiResponse::error('Tidak ada jadwal kerja pada tanggal ini', 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
$shift = $jadwal->shift;
|
||||||
|
$jamMasuk = $shift->jam_mulai ?? '00:00:00';
|
||||||
|
$jamPulang = $shift->jam_selesai ?? '00:00:00';
|
||||||
|
|
||||||
|
$statusJadwal = 'Normal';
|
||||||
|
$note = null;
|
||||||
|
|
||||||
|
$poinList = PenggunaanPoin::where('id_user', $user->id)
|
||||||
|
->whereDate('tanggal_penggunaan', $tanggal)
|
||||||
|
->where('id_status', 2)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
foreach ($poinList as $poin) {
|
||||||
|
if ($poin->id_pengurangan == 4 && $poin->jam_masuk_custom) {
|
||||||
|
$jamMasuk = substr($poin->jam_masuk_custom, 0, 5) . ':00';
|
||||||
|
$statusJadwal = 'Masuk Siang (Poin)';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($poin->id_pengurangan == 5 && $poin->jam_pulang_custom) {
|
||||||
|
$jamPulang = substr($poin->jam_pulang_custom, 0, 5) . ':00';
|
||||||
|
$statusJadwal = ($statusJadwal == 'Masuk Siang (Poin)') ? 'Full Custom' : 'Pulang Cepat (Poin)';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ApiResponse::success([
|
||||||
|
'tanggal' => Carbon::parse($tanggal, 'Asia/Jakarta')->translatedFormat('l, d F Y'),
|
||||||
|
'jam_masuk' => $jamMasuk,
|
||||||
|
'jam_pulang' => $jamPulang,
|
||||||
|
|
||||||
|
'jam_mulai' => $jamMasuk,
|
||||||
|
'jam_selesai' => $jamPulang,
|
||||||
|
|
||||||
|
'status_jadwal' => $statusJadwal,
|
||||||
|
'note' => $note,
|
||||||
|
], 'Jadwal ditemukan');
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return ApiResponse::error('Terjadi kesalahan: ' . $e->getMessage(), 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMonthlySchedule(Request $request)
|
||||||
|
{
|
||||||
|
|
||||||
|
$month = $request->month ?? Carbon::now()->month;
|
||||||
|
$year = $request->year ?? Carbon::now()->year;
|
||||||
|
|
||||||
|
try {
|
||||||
|
$user = Auth::user();
|
||||||
|
|
||||||
|
$startDate = Carbon::createFromDate($year, $month, 1)->startOfMonth();
|
||||||
|
$endDate = Carbon::createFromDate($year, $month, 1)->endOfMonth();
|
||||||
|
|
||||||
|
$jadwals = JadwalKerja::with(['shift'])
|
||||||
|
->where('id_user', $user->id)
|
||||||
|
->whereBetween('tanggal', [$startDate->toDateString(), $endDate->toDateString()])
|
||||||
|
->get()
|
||||||
|
->keyBy('tanggal');
|
||||||
|
|
||||||
|
$poinOverrides = PenggunaanPoin::where('id_user', $user->id)
|
||||||
|
->whereBetween('tanggal_penggunaan', [$startDate->toDateString(), $endDate->toDateString()])
|
||||||
|
->where('id_status', 2)
|
||||||
|
->get()
|
||||||
|
->groupBy('tanggal_penggunaan');
|
||||||
|
|
||||||
|
$presensis = Presensi::where('id_user', $user->id)
|
||||||
|
->whereBetween('tanggal', [$startDate->toDateString(), $endDate->toDateString()])
|
||||||
|
->get()
|
||||||
|
->keyBy('tanggal');
|
||||||
|
|
||||||
|
$hariLiburs = \App\Models\HariLibur::whereBetween('tanggal', [$startDate->toDateString(), $endDate->toDateString()])
|
||||||
|
->where(function($query) use ($user) {
|
||||||
|
$query->whereNull('id_kantor')
|
||||||
|
->orWhere('id_kantor', $user->id_kantor);
|
||||||
|
})
|
||||||
|
->get()
|
||||||
|
->keyBy(function ($item) {
|
||||||
|
return Carbon::parse($item->tanggal)->toDateString();
|
||||||
|
});
|
||||||
|
|
||||||
|
$results = [];
|
||||||
|
$period = CarbonPeriod::create($startDate, $endDate);
|
||||||
|
|
||||||
|
foreach ($period as $date) {
|
||||||
|
$dateStr = $date->toDateString();
|
||||||
|
$jadwalItem = $jadwals[$dateStr] ?? null;
|
||||||
|
$presensiItem = $presensis[$dateStr] ?? null;
|
||||||
|
$hariLiburItem = $hariLiburs[$dateStr] ?? null;
|
||||||
|
|
||||||
|
$dataHari = [
|
||||||
|
'tanggal' => $dateStr,
|
||||||
|
'hari' => $date->translatedFormat('l'),
|
||||||
|
'is_hari_kerja' => false,
|
||||||
|
'is_hari_libur' => $hariLiburItem ? true : false,
|
||||||
|
'keterangan_libur' => $hariLiburItem ? $hariLiburItem->keterangan : null,
|
||||||
|
'shift_nama' => $hariLiburItem ? $hariLiburItem->keterangan : 'Libur / Off',
|
||||||
|
'jam_masuk' => '-',
|
||||||
|
'jam_pulang' => '-',
|
||||||
|
'status_poin' => null,
|
||||||
|
'status_presensi' => $presensiItem ? 'Hadir' : 'Belum Absen',
|
||||||
|
'warna_kalender' => $hariLiburItem ? '#EF4444' : '#E0E0E0'
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($jadwalItem) {
|
||||||
|
$dataHari['is_hari_kerja'] = true;
|
||||||
|
|
||||||
|
$shift = $jadwalItem->shift;
|
||||||
|
$dataHari['shift_nama'] = $shift->nama_shift ?? 'Unknown Shift';
|
||||||
|
$dataHari['jam_masuk'] = $shift->jam_mulai ?? '00:00:00';
|
||||||
|
$dataHari['jam_pulang'] = $shift->jam_selesai ?? '00:00:00';
|
||||||
|
|
||||||
|
$dataHari['warna_kalender'] = '#3B82F6';
|
||||||
|
|
||||||
|
$poinFound = null;
|
||||||
|
|
||||||
|
foreach ($poinOverrides as $keyDate => $poins) {
|
||||||
|
if (Carbon::parse($keyDate)->toDateString() == $dateStr) {
|
||||||
|
$poinFound = $poins;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($poinFound) {
|
||||||
|
foreach ($poinFound as $poin) {
|
||||||
|
if ($poin->id_pengurangan == 4 && $poin->jam_masuk_custom) {
|
||||||
|
$dataHari['jam_masuk'] = substr($poin->jam_masuk_custom, 0, 5) . ':00';
|
||||||
|
$dataHari['status_poin'] = 'Masuk Siang';
|
||||||
|
$dataHari['warna_kalender'] = '#F59E0B';
|
||||||
|
}
|
||||||
|
if ($poin->id_pengurangan == 5 && $poin->jam_pulang_custom) {
|
||||||
|
$dataHari['jam_pulang'] = substr($poin->jam_pulang_custom, 0, 5) . ':00';
|
||||||
|
$dataHari['status_poin'] = $dataHari['status_poin'] ? 'Full Custom' : 'Pulang Cepat';
|
||||||
|
$dataHari['warna_kalender'] = '#F59E0B';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($presensiItem) {
|
||||||
|
$dataHari['warna_kalender'] = '#10B981';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$results[] = $dataHari;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ApiResponse::success($results, 'Data kalender berhasil dimuat');
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return ApiResponse::error('Terjadi kesalahan: ' . $e->getMessage(), 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Helpers\ApiResponse;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Requests\StoreSignatureRequest;
|
||||||
|
use App\Models\TandaTangan;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
|
class SignatureApiController extends Controller
|
||||||
|
{
|
||||||
|
public function show()
|
||||||
|
{
|
||||||
|
$ttd = TandaTangan::where('id_user', Auth::id())
|
||||||
|
->active()
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if (!$ttd) {
|
||||||
|
return ApiResponse::notFound('Belum ada tanda tangan.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return ApiResponse::success([
|
||||||
|
'id_tanda_tangan' => $ttd->id_tanda_tangan,
|
||||||
|
'file_ttd' => asset('storage/' . $ttd->file_ttd),
|
||||||
|
'is_active' => $ttd->is_active,
|
||||||
|
'created_at' => $ttd->created_at,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(StoreSignatureRequest $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$base64 = $request->signature_data;
|
||||||
|
|
||||||
|
if (str_contains($base64, ',')) {
|
||||||
|
$base64 = explode(',', $base64)[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
$imageData = base64_decode($base64);
|
||||||
|
if ($imageData === false) {
|
||||||
|
return ApiResponse::error('Data tanda tangan tidak valid.', 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
$fileName = 'uploads/ttd/' . Auth::id() . '_' . time() . '.png';
|
||||||
|
Storage::disk('public')->put($fileName, $imageData);
|
||||||
|
|
||||||
|
TandaTangan::where('id_user', Auth::id())->update(['is_active' => false]);
|
||||||
|
|
||||||
|
$ttd = TandaTangan::create([
|
||||||
|
'id_user' => Auth::id(),
|
||||||
|
'file_ttd' => $fileName,
|
||||||
|
'is_active' => true,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return ApiResponse::success([
|
||||||
|
'id_tanda_tangan' => $ttd->id_tanda_tangan,
|
||||||
|
'file_ttd' => asset('storage/' . $ttd->file_ttd),
|
||||||
|
], 'Tanda tangan berhasil disimpan.', 201);
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return ApiResponse::error('Gagal menyimpan tanda tangan: ' . $e->getMessage(), 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy($id)
|
||||||
|
{
|
||||||
|
$ttd = TandaTangan::where('id_user', Auth::id())
|
||||||
|
->where('id_tanda_tangan', $id)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if (!$ttd) {
|
||||||
|
return ApiResponse::notFound('Tanda tangan tidak ditemukan.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($ttd->file_ttd && Storage::disk('public')->exists($ttd->file_ttd)) {
|
||||||
|
Storage::disk('public')->delete($ttd->file_ttd);
|
||||||
|
}
|
||||||
|
|
||||||
|
$ttd->delete();
|
||||||
|
|
||||||
|
return ApiResponse::success(null, 'Tanda tangan berhasil dihapus.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,213 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Helpers\ApiResponse;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\PengajuanIzin;
|
||||||
|
use App\Models\JenisIzin;
|
||||||
|
use App\Models\SuratIzin;
|
||||||
|
use App\Models\TandaTangan;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
|
||||||
|
class SubmissionController extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
public function types()
|
||||||
|
{
|
||||||
|
$types = JenisIzin::all();
|
||||||
|
return ApiResponse::success($types);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(\App\Http\Requests\StorePengajuanIzinRequest $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$user = Auth::user();
|
||||||
|
|
||||||
|
$jenisIzin = JenisIzin::find($request->id_jenis_izin);
|
||||||
|
if ($jenisIzin && $jenisIzin->nama_izin == 'Cuti') {
|
||||||
|
$tanggalMulai = Carbon::parse($request->tanggal_mulai);
|
||||||
|
$minDate = Carbon::now()->addDays(7)->startOfDay();
|
||||||
|
|
||||||
|
if ($tanggalMulai->lt($minDate)) {
|
||||||
|
return ApiResponse::error('Pengajuan Cuti minimal H-7!', 400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DB::beginTransaction();
|
||||||
|
|
||||||
|
$path = null;
|
||||||
|
if ($request->hasFile('bukti_file')) {
|
||||||
|
$path = $request->file('bukti_file')->store('uploads/izin', 'public');
|
||||||
|
}
|
||||||
|
|
||||||
|
$submission = PengajuanIzin::create([
|
||||||
|
'id_user' => $user->id,
|
||||||
|
'id_jenis_izin' => $request->id_jenis_izin,
|
||||||
|
'tanggal_mulai' => $request->tanggal_mulai,
|
||||||
|
'tanggal_selesai' => $request->tanggal_selesai,
|
||||||
|
'alasan' => $request->alasan,
|
||||||
|
'bukti_file' => $path,
|
||||||
|
'id_status' => 1
|
||||||
|
]);
|
||||||
|
|
||||||
|
$ttdAktif = TandaTangan::where('id_user', $user->id)->active()->first();
|
||||||
|
|
||||||
|
$namaJenisIzin = $jenisIzin->nama_izin ?? 'Izin';
|
||||||
|
$tglMulai = Carbon::parse($request->tanggal_mulai)->translatedFormat('d F Y');
|
||||||
|
$tglSelesai = Carbon::parse($request->tanggal_selesai)->translatedFormat('d F Y');
|
||||||
|
|
||||||
|
$isiSurat = "Dengan hormat,\n\n"
|
||||||
|
. "Saya yang bertanda tangan di bawah ini:\n"
|
||||||
|
. "Nama: {$user->nama_lengkap}\n"
|
||||||
|
. "NIK: {$user->nik}\n"
|
||||||
|
. "Jabatan: " . ($user->jabatan->nama_jabatan ?? '-') . "\n"
|
||||||
|
. "Divisi: " . ($user->divisi->nama_divisi ?? '-') . "\n\n"
|
||||||
|
. "Dengan ini mengajukan {$namaJenisIzin} mulai tanggal {$tglMulai} sampai dengan {$tglSelesai}.\n\n"
|
||||||
|
. "Alasan: {$request->alasan}\n\n"
|
||||||
|
. "Demikian surat ini saya buat dengan sebenar-benarnya. "
|
||||||
|
. "Atas perhatian dan persetujuannya, saya ucapkan terima kasih.";
|
||||||
|
|
||||||
|
$suratIzin = null;
|
||||||
|
if ($jenisIzin && $jenisIzin->nama_izin == 'Cuti') {
|
||||||
|
$suratIzin = SuratIzin::create([
|
||||||
|
'id_izin' => $submission->id_izin,
|
||||||
|
'id_user' => $user->id,
|
||||||
|
'id_ttd_pengaju' => $ttdAktif?->id_tanda_tangan,
|
||||||
|
'isi_surat' => $isiSurat,
|
||||||
|
'status_surat' => 'menunggu_manajer',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
DB::commit();
|
||||||
|
|
||||||
|
$responseData = $submission->toArray();
|
||||||
|
if ($suratIzin) {
|
||||||
|
$responseData['surat_izin'] = [
|
||||||
|
'id_surat' => $suratIzin->id_surat,
|
||||||
|
'nomor_surat' => $suratIzin->nomor_surat,
|
||||||
|
'status_surat' => $suratIzin->status_surat,
|
||||||
|
'has_ttd' => $ttdAktif !== null,
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
$responseData['surat_izin'] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$message = 'Pengajuan & surat izin berhasil dibuat.';
|
||||||
|
if (!$ttdAktif) {
|
||||||
|
$message .= ' (TTD belum tersedia, silakan buat di menu Profil)';
|
||||||
|
}
|
||||||
|
|
||||||
|
return ApiResponse::success($responseData, $message, 201);
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
DB::rollBack();
|
||||||
|
return ApiResponse::error('Gagal mengirim pengajuan: ' . $e->getMessage(), 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @OA\Put(
|
||||||
|
* path="/api/submission/{id}",
|
||||||
|
* tags={"Submission"},
|
||||||
|
* summary="Update Submission",
|
||||||
|
* security={{"bearerAuth":{}}},
|
||||||
|
* @OA\Parameter(
|
||||||
|
* name="id",
|
||||||
|
* in="path",
|
||||||
|
* required=true,
|
||||||
|
* @OA\Schema(type="integer")
|
||||||
|
* ),
|
||||||
|
* @OA\RequestBody(
|
||||||
|
* required=true,
|
||||||
|
* @OA\MediaType(
|
||||||
|
* mediaType="multipart/form-data",
|
||||||
|
* @OA\Schema(
|
||||||
|
* required={"id_jenis_izin", "tanggal_mulai", "tanggal_selesai", "alasan"},
|
||||||
|
* @OA\Property(property="id_jenis_izin", type="integer", example=1),
|
||||||
|
* @OA\Property(property="tanggal_mulai", type="string", format="date"),
|
||||||
|
* @OA\Property(property="tanggal_selesai", type="string", format="date"),
|
||||||
|
* @OA\Property(property="alasan", type="string"),
|
||||||
|
* @OA\Property(property="bukti_file", type="string", format="binary")
|
||||||
|
* )
|
||||||
|
* )
|
||||||
|
* ),
|
||||||
|
* @OA\Response(
|
||||||
|
* response=200,
|
||||||
|
* description="Submission updated",
|
||||||
|
* @OA\JsonContent(
|
||||||
|
* @OA\Property(property="success", type="boolean", example=true),
|
||||||
|
* @OA\Property(property="message", type="string")
|
||||||
|
* )
|
||||||
|
* )
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
public function update(\App\Http\Requests\UpdatePengajuanIzinRequest $request, $id)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$submission = PengajuanIzin::where('id_user', Auth::id())
|
||||||
|
->where('id_izin', $id)
|
||||||
|
->where('id_status', 1)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if (!$submission) {
|
||||||
|
return ApiResponse::error('Pengajuan tidak ditemukan atau sudah diproses.', 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
DB::beginTransaction();
|
||||||
|
|
||||||
|
$data = $request->validated();
|
||||||
|
|
||||||
|
if ($request->hasFile('bukti_file')) {
|
||||||
|
|
||||||
|
if ($submission->bukti_file && \Illuminate\Support\Facades\Storage::disk('public')->exists($submission->bukti_file)) {
|
||||||
|
\Illuminate\Support\Facades\Storage::disk('public')->delete($submission->bukti_file);
|
||||||
|
}
|
||||||
|
$data['bukti_file'] = $request->file('bukti_file')->store('uploads/izin', 'public');
|
||||||
|
}
|
||||||
|
|
||||||
|
$submission->update($data);
|
||||||
|
|
||||||
|
DB::commit();
|
||||||
|
|
||||||
|
return ApiResponse::success(null, 'Pengajuan berhasil diperbarui.');
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
DB::rollBack();
|
||||||
|
return ApiResponse::error('Gagal memperbarui pengajuan: ' . $e->getMessage(), 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function history(Request $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$query = PengajuanIzin::with(['jenisIzin', 'statusPengajuan'])
|
||||||
|
->where('id_user', Auth::id());
|
||||||
|
|
||||||
|
if ($request->has('status')) {
|
||||||
|
$statusParam = $request->get('status');
|
||||||
|
|
||||||
|
$statusId = match ($statusParam) {
|
||||||
|
'pending' => 1,
|
||||||
|
'approved' => 2,
|
||||||
|
'rejected' => 3,
|
||||||
|
default => null
|
||||||
|
};
|
||||||
|
|
||||||
|
if ($statusId) {
|
||||||
|
$query->where('id_status', $statusId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$history = $query->orderBy('created_at', 'desc')->paginate(10);
|
||||||
|
|
||||||
|
return ApiResponse::success($history);
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return ApiResponse::error('Gagal memuat riwayat: ' . $e->getMessage(), 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,157 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Helpers\ApiResponse;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Requests\StoreSuratIzinRequest;
|
||||||
|
use App\Models\SuratIzin;
|
||||||
|
use App\Models\PengajuanIzin;
|
||||||
|
use App\Models\TandaTangan;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
|
class SuratIzinApiController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$surat = SuratIzin::with([
|
||||||
|
'pengajuanIzin.jenisIzin',
|
||||||
|
'tandaTanganPengaju',
|
||||||
|
'approvals.approver',
|
||||||
|
'approvals.tandaTanganApprover',
|
||||||
|
])
|
||||||
|
->where('id_user', Auth::id())
|
||||||
|
->orderBy('created_at', 'desc')
|
||||||
|
->paginate(10);
|
||||||
|
|
||||||
|
$data = $surat->through(function ($item) {
|
||||||
|
return $this->formatSurat($item);
|
||||||
|
});
|
||||||
|
|
||||||
|
return ApiResponse::success($data);
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return ApiResponse::error('Gagal memuat daftar surat: ' . $e->getMessage(), 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(StoreSuratIzinRequest $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$user = Auth::user();
|
||||||
|
|
||||||
|
$pengajuan = PengajuanIzin::with('jenisIzin')
|
||||||
|
->where('id_izin', $request->id_izin)
|
||||||
|
->where('id_user', $user->id)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if (!$pengajuan) {
|
||||||
|
return ApiResponse::notFound('Pengajuan izin tidak ditemukan.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$existing = SuratIzin::where('id_izin', $request->id_izin)->first();
|
||||||
|
if ($existing) {
|
||||||
|
return ApiResponse::error('Surat izin untuk pengajuan ini sudah ada.', 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
$ttd = TandaTangan::where('id_user', $user->id)->active()->first();
|
||||||
|
if (!$ttd) {
|
||||||
|
return ApiResponse::error('Anda belum memiliki tanda tangan digital. Silakan buat terlebih dahulu.', 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
DB::beginTransaction();
|
||||||
|
|
||||||
|
$surat = SuratIzin::create([
|
||||||
|
'id_izin' => $pengajuan->id_izin,
|
||||||
|
'id_user' => $user->id,
|
||||||
|
'isi_surat' => $request->isi_surat,
|
||||||
|
'id_ttd_pengaju' => $ttd->id_tanda_tangan,
|
||||||
|
'status_surat' => 'menunggu_manajer',
|
||||||
|
]);
|
||||||
|
|
||||||
|
DB::commit();
|
||||||
|
|
||||||
|
$surat->load(['tandaTanganPengaju', 'approvals']);
|
||||||
|
|
||||||
|
return ApiResponse::success(
|
||||||
|
$this->formatSurat($surat),
|
||||||
|
'Surat izin berhasil dibuat.',
|
||||||
|
201
|
||||||
|
);
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
DB::rollBack();
|
||||||
|
return ApiResponse::error('Gagal membuat surat izin: ' . $e->getMessage(), 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function show($id)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$surat = SuratIzin::with([
|
||||||
|
'pengajuanIzin.jenisIzin',
|
||||||
|
'user.jabatan',
|
||||||
|
'user.divisi',
|
||||||
|
'tandaTanganPengaju',
|
||||||
|
'approvals.approver.jabatan',
|
||||||
|
'approvals.tandaTanganApprover',
|
||||||
|
])
|
||||||
|
->where('id_user', Auth::id())
|
||||||
|
->where('id_surat', $id)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if (!$surat) {
|
||||||
|
return ApiResponse::notFound('Surat izin tidak ditemukan.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return ApiResponse::success($this->formatSurat($surat, true));
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return ApiResponse::error('Gagal memuat detail surat: ' . $e->getMessage(), 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function formatSurat(SuratIzin $surat, bool $detail = false): array
|
||||||
|
{
|
||||||
|
$data = [
|
||||||
|
'id_surat' => $surat->id_surat,
|
||||||
|
'nomor_surat' => $surat->nomor_surat,
|
||||||
|
'status_surat' => $surat->status_surat,
|
||||||
|
'jenis_izin' => $surat->pengajuanIzin?->jenisIzin?->nama_izin ?? 'N/A',
|
||||||
|
'created_at' => $surat->created_at?->toISOString(),
|
||||||
|
'ttd_pengaju' => $surat->tandaTanganPengaju ? asset('storage/' . $surat->tandaTanganPengaju->file_ttd) : null,
|
||||||
|
'approvals' => $surat->approvals->map(function ($approval) {
|
||||||
|
return [
|
||||||
|
'tahap' => $approval->tahap,
|
||||||
|
'tahap_label' => $approval->tahap == 1 ? 'Manajer' : 'HRD',
|
||||||
|
'status' => $approval->status,
|
||||||
|
'approver_nama' => $approval->approver?->nama_lengkap ?? 'N/A',
|
||||||
|
'approver_jabatan' => $approval->approver?->jabatan?->nama_jabatan ?? 'N/A',
|
||||||
|
'ttd_approver' => $approval->tandaTanganApprover ? asset('storage/' . $approval->tandaTanganApprover->file_ttd) : null,
|
||||||
|
'catatan' => $approval->catatan,
|
||||||
|
'created_at' => $approval->created_at?->toISOString(),
|
||||||
|
];
|
||||||
|
})->toArray(),
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($detail) {
|
||||||
|
$data['isi_surat'] = $surat->isi_surat;
|
||||||
|
$data['pengaju'] = [
|
||||||
|
'nama' => $surat->user?->nama_lengkap,
|
||||||
|
'nik' => $surat->user?->nik,
|
||||||
|
'jabatan' => $surat->user?->jabatan?->nama_jabatan ?? 'N/A',
|
||||||
|
'divisi' => $surat->user?->divisi?->nama_divisi ?? 'N/A',
|
||||||
|
];
|
||||||
|
$data['pengajuan'] = [
|
||||||
|
'id_izin' => $surat->pengajuanIzin?->id_izin,
|
||||||
|
'tanggal_mulai' => $surat->pengajuanIzin?->tanggal_mulai,
|
||||||
|
'tanggal_selesai' => $surat->pengajuanIzin?->tanggal_selesai,
|
||||||
|
'alasan' => $surat->pengajuanIzin?->alasan,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
|
class AuthController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
|
||||||
|
if (Auth::check()) {
|
||||||
|
return redirect()->route('dashboard');
|
||||||
|
}
|
||||||
|
return view('auth.login');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function login(Request $request)
|
||||||
|
{
|
||||||
|
$credentials = $request->validate([
|
||||||
|
'email' => 'required|email',
|
||||||
|
'password' => 'required',
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (Auth::attempt($credentials)) {
|
||||||
|
$user = Auth::user();
|
||||||
|
if ($user->status_aktif == 0) {
|
||||||
|
Auth::logout();
|
||||||
|
if ($request->ajax() || $request->wantsJson()) {
|
||||||
|
return response()->json([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Akun Anda telah dinonaktifkan.'
|
||||||
|
], 403);
|
||||||
|
}
|
||||||
|
return back()->with('error', 'Akun Anda telah dinonaktifkan.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$request->session()->regenerate();
|
||||||
|
|
||||||
|
if ($request->ajax() || $request->wantsJson()) {
|
||||||
|
return response()->json([
|
||||||
|
'success' => true,
|
||||||
|
'message' => 'Login berhasil!',
|
||||||
|
'redirect' => route('dashboard')
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->route('dashboard');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->ajax() || $request->wantsJson()) {
|
||||||
|
return response()->json([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Email atau Password yang Anda masukkan salah.'
|
||||||
|
], 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
return back()
|
||||||
|
->withInput($request->only('email'))
|
||||||
|
->with('error', 'Email atau Password yang Anda masukkan salah.')
|
||||||
|
->withErrors(['email' => 'Email atau Password yang Anda masukkan salah.']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function logout(Request $request)
|
||||||
|
{
|
||||||
|
Auth::logout();
|
||||||
|
$request->session()->invalidate();
|
||||||
|
$request->session()->regenerateToken();
|
||||||
|
return redirect('/login');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @OA\Info(
|
||||||
|
* version="1.0.0",
|
||||||
|
* title="MPG HRIS API",
|
||||||
|
* description="API Documentation"
|
||||||
|
* )
|
||||||
|
* @OA\Server(
|
||||||
|
* url="http://localhost/api",
|
||||||
|
* description="API Server"
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
class Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class CutiController extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$search = $request->input('search');
|
||||||
|
|
||||||
|
$query = User::with(['jabatan', 'divisi'])->whereHas('roles', function($q) {
|
||||||
|
$q->where('nama_role', '!=', 'super_admin');
|
||||||
|
});
|
||||||
|
|
||||||
|
if ($search) {
|
||||||
|
$query->where('nama_lengkap', 'like', '%' . $search . '%')
|
||||||
|
->orWhere('nik', 'like', '%' . $search . '%');
|
||||||
|
}
|
||||||
|
|
||||||
|
$pegawai = $query->orderBy('nama_lengkap', 'asc')->paginate(15);
|
||||||
|
|
||||||
|
return view('cuti.index', compact('pegawai', 'search'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(Request $request, $id)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'sisa_cuti' => 'required|integer|min:0',
|
||||||
|
'alasan' => 'nullable|string|max:255'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$user = User::findOrFail($id);
|
||||||
|
|
||||||
|
$sisaLama = $user->sisa_cuti;
|
||||||
|
$user->update([
|
||||||
|
'sisa_cuti' => $request->sisa_cuti
|
||||||
|
]);
|
||||||
|
|
||||||
|
return redirect()->back()->with('success', 'Sisa cuti ' . $user->nama_lengkap . ' berhasil diperbarui.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function resetMassal(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'jumlah_hari' => 'required|integer|min:0'
|
||||||
|
]);
|
||||||
|
|
||||||
|
User::query()->update([
|
||||||
|
'sisa_cuti' => $request->jumlah_hari
|
||||||
|
]);
|
||||||
|
|
||||||
|
return redirect()->back()->with('success', 'Sisa cuti semua pegawai berhasil di-reset menjadi ' . $request->jumlah_hari . ' hari.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Models\Kantor;
|
||||||
|
use App\Models\Presensi;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
|
||||||
|
class DashboardController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$hariIni = Carbon::today()->format('Y-m-d');
|
||||||
|
$totalPegawai = User::where('status_aktif', 1)->count();
|
||||||
|
|
||||||
|
$rekapRaw = Presensi::whereDate('tanggal', $hariIni)
|
||||||
|
->selectRaw("
|
||||||
|
SUM(CASE WHEN id_status IN (1,2) THEN 1 ELSE 0 END) as hadir,
|
||||||
|
SUM(CASE WHEN id_status = 2 THEN 1 ELSE 0 END) as terlambat,
|
||||||
|
SUM(CASE WHEN id_status = 3 THEN 1 ELSE 0 END) as izin,
|
||||||
|
SUM(CASE WHEN id_status = 4 THEN 1 ELSE 0 END) as sakit,
|
||||||
|
SUM(CASE WHEN id_status = 5 THEN 1 ELSE 0 END) as alpha
|
||||||
|
")->first();
|
||||||
|
|
||||||
|
$rekap = [
|
||||||
|
'hadir' => $rekapRaw->hadir ?? 0,
|
||||||
|
'izin' => $rekapRaw->izin ?? 0,
|
||||||
|
'sakit' => $rekapRaw->sakit ?? 0,
|
||||||
|
'alpha' => $rekapRaw->alpha ?? 0,
|
||||||
|
'terlambat' => $rekapRaw->terlambat ?? 0
|
||||||
|
];
|
||||||
|
|
||||||
|
$recentActivities = Presensi::with(['user.jabatan'])
|
||||||
|
->whereDate('tanggal', $hariIni)
|
||||||
|
->whereNotNull('jam_masuk')
|
||||||
|
->orderBy('jam_masuk', 'desc')
|
||||||
|
->take(5)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
$pendingIzin = \App\Models\PengajuanIzin::with('user')->where('id_status', 1)->orderBy('created_at', 'desc')->take(5)->get();
|
||||||
|
$pendingSuratIzin = \App\Models\SuratIzin::with('user')->whereIn('status_surat', ['menunggu_manajer', 'menunggu_hrd'])->orderBy('created_at', 'desc')->take(5)->get();
|
||||||
|
$pendingLembur = \App\Models\Lembur::with('user')->where('id_status', 1)->orderBy('created_at', 'desc')->take(5)->get();
|
||||||
|
$pendingPoin = \App\Models\PenggunaanPoin::with('user')->where('id_status', 1)->orderBy('created_at', 'desc')->take(5)->get();
|
||||||
|
$pendingPresensi = Presensi::with('user')->where('id_validasi', 2)->orderBy('created_at', 'desc')->take(5)->get();
|
||||||
|
|
||||||
|
$pengajuanPending = [
|
||||||
|
'izin' => $pendingIzin,
|
||||||
|
'surat_izin' => $pendingSuratIzin,
|
||||||
|
'lembur' => $pendingLembur,
|
||||||
|
'poin' => $pendingPoin,
|
||||||
|
'presensi' => $pendingPresensi
|
||||||
|
];
|
||||||
|
|
||||||
|
$startDate = Carbon::today()->subDays(6)->format('Y-m-d');
|
||||||
|
$endDate = $hariIni;
|
||||||
|
|
||||||
|
$chartRaw = Presensi::whereBetween('tanggal', [$startDate, $endDate])
|
||||||
|
->whereIn('id_status', [1, 2])
|
||||||
|
->selectRaw("DATE(tanggal) as tgl, COUNT(*) as total")
|
||||||
|
->groupBy('tgl')
|
||||||
|
->orderBy('tgl')
|
||||||
|
->pluck('total', 'tgl');
|
||||||
|
|
||||||
|
$chartLabels = [];
|
||||||
|
$chartData = [];
|
||||||
|
|
||||||
|
for ($i = 6; $i >= 0; $i--) {
|
||||||
|
$date = Carbon::today()->subDays($i);
|
||||||
|
$chartLabels[] = $date->format('d/m');
|
||||||
|
$chartData[] = $chartRaw->get($date->format('Y-m-d'), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('dashboard.index', compact('rekap', 'recentActivities', 'pengajuanPending', 'chartLabels', 'chartData', 'totalPegawai'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\Divisi;
|
||||||
|
use App\Http\Requests\StoreDivisiRequest;
|
||||||
|
use App\Http\Requests\UpdateDivisiRequest;
|
||||||
|
|
||||||
|
class DivisiController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$divisi = Divisi::latest()->paginate(10);
|
||||||
|
return view('divisi.index', compact('divisi'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(StoreDivisiRequest $request)
|
||||||
|
{
|
||||||
|
|
||||||
|
Divisi::create($request->validated());
|
||||||
|
|
||||||
|
return redirect()->back()->with('success', 'Divisi berhasil ditambahkan.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(UpdateDivisiRequest $request, $id)
|
||||||
|
{
|
||||||
|
$divisi = Divisi::findOrFail($id);
|
||||||
|
|
||||||
|
$divisi->update($request->validated());
|
||||||
|
|
||||||
|
return redirect()->back()->with('success', 'Divisi berhasil diperbarui.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy($id)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Divisi::findOrFail($id)->delete();
|
||||||
|
return redirect()->back()->with('success', 'Divisi berhasil dihapus.');
|
||||||
|
} catch (\Illuminate\Database\QueryException $e) {
|
||||||
|
if ($e->getCode() === '23000') {
|
||||||
|
return redirect()->back()->with('error', 'Divisi tidak bisa dihapus karena masih digunakan oleh data pegawai.');
|
||||||
|
}
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Models\DataWajah;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
|
class FaceApprovalController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$users = User::whereHas('dataWajah', function($q) {
|
||||||
|
$q->where('is_verified', 0);
|
||||||
|
})
|
||||||
|
->with(['jabatan', 'divisi'])
|
||||||
|
->get();
|
||||||
|
|
||||||
|
$users->each(function ($user) {
|
||||||
|
$storagePath = "face_datasets/{$user->id}";
|
||||||
|
$poses = ['depan', 'kanan', 'kiri', 'bawah'];
|
||||||
|
$fotoList = [];
|
||||||
|
|
||||||
|
foreach ($poses as $pose) {
|
||||||
|
$extensions = ['jpg', 'jpeg', 'png'];
|
||||||
|
foreach ($extensions as $ext) {
|
||||||
|
$filePath = "{$storagePath}/user_{$user->id}_{$pose}.{$ext}";
|
||||||
|
if (Storage::disk('local')->exists($filePath)) {
|
||||||
|
$fotoList[$pose] = $filePath;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$user->face_photos = $fotoList;
|
||||||
|
});
|
||||||
|
|
||||||
|
return view('face-approval.index', compact('users'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function approve($id)
|
||||||
|
{
|
||||||
|
$user = User::findOrFail($id);
|
||||||
|
|
||||||
|
if ($user->dataWajah) {
|
||||||
|
$user->dataWajah->update(['is_verified' => 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->back()->with('success', 'Wajah karyawan berhasil diverifikasi. Karyawan kini bisa melakukan presensi.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function reject($id)
|
||||||
|
{
|
||||||
|
$user = User::findOrFail($id);
|
||||||
|
|
||||||
|
if ($user->dataWajah) {
|
||||||
|
$user->dataWajah->delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
$user->update(['is_face_registered' => 0]);
|
||||||
|
|
||||||
|
$storagePath = "face_datasets/{$user->id}";
|
||||||
|
if (Storage::disk('local')->exists($storagePath)) {
|
||||||
|
Storage::disk('local')->deleteDirectory($storagePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->back()->with('success', 'Wajah ditolak. Karyawan diminta melakukan registrasi ulang.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function showPhoto($userId, $pose)
|
||||||
|
{
|
||||||
|
$extensions = ['jpg', 'jpeg', 'png'];
|
||||||
|
foreach ($extensions as $ext) {
|
||||||
|
$filePath = "face_datasets/{$userId}/user_{$userId}_{$pose}.{$ext}";
|
||||||
|
if (Storage::disk('local')->exists($filePath)) {
|
||||||
|
return response()->file(Storage::disk('local')->path($filePath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abort(404);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,105 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\HariLibur;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
|
||||||
|
class HariLiburController extends Controller
|
||||||
|
{
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$query = HariLibur::with('kantor');
|
||||||
|
|
||||||
|
if ($request->filled('search')) {
|
||||||
|
$query->where('keterangan', 'like', '%' . $request->search . '%')
|
||||||
|
->orWhere('tanggal', 'like', '%' . $request->search . '%');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->filled('id_kantor')) {
|
||||||
|
$query->where('id_kantor', $request->id_kantor);
|
||||||
|
}
|
||||||
|
|
||||||
|
$hariLiburs = $query->orderBy('tanggal', 'desc')->paginate(10)->withQueryString();
|
||||||
|
$kantors = \App\Models\Kantor::all();
|
||||||
|
|
||||||
|
return view('hari_libur.index', compact('hariLiburs', 'kantors'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'tanggal' => 'required|date',
|
||||||
|
'keterangan' => 'required|string|max:255',
|
||||||
|
'id_kantor' => 'nullable|exists:kantor,id_kantor',
|
||||||
|
]);
|
||||||
|
|
||||||
|
HariLibur::create($request->all());
|
||||||
|
|
||||||
|
return redirect()->route('hari-libur.index')
|
||||||
|
->with('success', 'Hari libur berhasil ditambahkan.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(Request $request, $id)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'tanggal' => 'required|date',
|
||||||
|
'keterangan' => 'required|string|max:255',
|
||||||
|
'id_kantor' => 'nullable|exists:kantor,id_kantor',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$hariLibur = HariLibur::where('id', '=', $id)->first() ?? HariLibur::where('id_hari_libur', '=', $id)->firstOrFail();
|
||||||
|
$hariLibur->update($request->all());
|
||||||
|
|
||||||
|
return redirect()->route('hari-libur.index')
|
||||||
|
->with('success', 'Hari libur berhasil diperbarui.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy($id)
|
||||||
|
{
|
||||||
|
$hariLibur = HariLibur::where('id', '=', $id)->first() ?? HariLibur::where('id_hari_libur', '=', $id)->firstOrFail();
|
||||||
|
$hariLibur->delete();
|
||||||
|
|
||||||
|
return redirect()->route('hari-libur.index')
|
||||||
|
->with('success', 'Hari libur berhasil dihapus.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function syncHolidays(Request $request)
|
||||||
|
{
|
||||||
|
$year = $request->get('year', date('Y'));
|
||||||
|
|
||||||
|
try {
|
||||||
|
$response = \Illuminate\Support\Facades\Http::withoutVerifying()->get("https://api-hari-libur.vercel.app/api?year={$year}");
|
||||||
|
|
||||||
|
if ($response->successful()) {
|
||||||
|
$body = $response->json();
|
||||||
|
$holidays = $body['data'] ?? [];
|
||||||
|
$count = 0;
|
||||||
|
|
||||||
|
foreach ($holidays as $h) {
|
||||||
|
if (isset($h['date'])) {
|
||||||
|
$tanggal = $h['date'];
|
||||||
|
$keterangan = $h['description'];
|
||||||
|
|
||||||
|
$exists = HariLibur::where('tanggal', '=', $tanggal)->exists();
|
||||||
|
if (!$exists) {
|
||||||
|
HariLibur::create(['tanggal' => $tanggal, 'keterangan' => $keterangan]);
|
||||||
|
$count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->route('hari-libur.index')
|
||||||
|
->with('success', "Berhasil sinkronisasi {$count} hari libur baru untuk tahun {$year}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->route('hari-libur.index')
|
||||||
|
->with('error', 'Gagal mengambil data dari API Hari Libur.');
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return redirect()->route('hari-libur.index')
|
||||||
|
->with('error', 'Terjadi kesalahan: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\Jabatan;
|
||||||
|
use App\Http\Requests\StoreJabatanRequest;
|
||||||
|
use App\Http\Requests\UpdateJabatanRequest;
|
||||||
|
|
||||||
|
class JabatanController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$jabatan = Jabatan::latest()->paginate(10);
|
||||||
|
return view('jabatan.index', compact('jabatan'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(StoreJabatanRequest $request)
|
||||||
|
{
|
||||||
|
Jabatan::create($request->validated());
|
||||||
|
return redirect()->back()->with('success', 'Jabatan berhasil ditambahkan.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(UpdateJabatanRequest $request, $id)
|
||||||
|
{
|
||||||
|
$jabatan = Jabatan::findOrFail($id);
|
||||||
|
$jabatan->update($request->validated());
|
||||||
|
return redirect()->back()->with('success', 'Jabatan berhasil diperbarui.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy($id)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Jabatan::findOrFail($id)->delete();
|
||||||
|
return redirect()->back()->with('success', 'Jabatan berhasil dihapus.');
|
||||||
|
} catch (\Illuminate\Database\QueryException $e) {
|
||||||
|
if ($e->getCode() === '23000') {
|
||||||
|
return redirect()->back()->with('error', 'Jabatan tidak bisa dihapus karena masih digunakan oleh data pegawai.');
|
||||||
|
}
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,352 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\JadwalKerja;
|
||||||
|
use App\Models\ShiftKerja;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Models\Kantor;
|
||||||
|
use App\Models\Divisi;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use App\Models\PenggunaanPoin;
|
||||||
|
use App\Services\PoinService;
|
||||||
|
|
||||||
|
class JadwalController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$kantor = Kantor::all();
|
||||||
|
$divisi = Divisi::all();
|
||||||
|
$shifts = ShiftKerja::all()->map(function ($s) {
|
||||||
|
$s->color = $this->getShiftColor($s->nama_shift);
|
||||||
|
return $s;
|
||||||
|
});
|
||||||
|
|
||||||
|
$pegawai = User::where('status_aktif', 1)->orderBy('nama_lengkap', 'asc')->get();
|
||||||
|
|
||||||
|
return view('jadwal.index', compact('kantor', 'divisi', 'shifts', 'pegawai'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEvents(Request $request)
|
||||||
|
{
|
||||||
|
$start = Carbon::parse($request->start)->format('Y-m-d');
|
||||||
|
$end = Carbon::parse($request->end)->format('Y-m-d');
|
||||||
|
|
||||||
|
$query = JadwalKerja::with(['user.kantor', 'user.jabatan', 'shift'])
|
||||||
|
->whereDate('tanggal', '>=', $start)
|
||||||
|
->whereDate('tanggal', '<=', $end);
|
||||||
|
|
||||||
|
if ($request->filled('filter_kantor') && $request->filter_kantor != "") {
|
||||||
|
$query->whereHas('user', function ($q) use ($request) {
|
||||||
|
$q->where('id_kantor', $request->filter_kantor);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->filled('filter_divisi') && $request->filter_divisi != "") {
|
||||||
|
$query->whereHas('user', function ($q) use ($request) {
|
||||||
|
$q->where('id_divisi', $request->filter_divisi);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$jadwals = $query->get();
|
||||||
|
|
||||||
|
$poinUsed = PenggunaanPoin::with('jenisPengurangan')
|
||||||
|
->whereBetween('tanggal_penggunaan', [$start, $end])
|
||||||
|
->where('id_status', 2)
|
||||||
|
->get()
|
||||||
|
->groupBy(function ($item) {
|
||||||
|
return $item->id_user . '-' . $item->tanggal_penggunaan->format('Y-m-d');
|
||||||
|
});
|
||||||
|
|
||||||
|
$events = [];
|
||||||
|
|
||||||
|
foreach ($jadwals as $jadwalItem) {
|
||||||
|
$key = $jadwalItem->id_user . '-' . $jadwalItem->tanggal;
|
||||||
|
|
||||||
|
$shiftName = $jadwalItem->shift?->nama_shift ?? 'Shift ?';
|
||||||
|
$jamMulai = $jadwalItem->shift?->jam_mulai ?? '00:00:00';
|
||||||
|
$jamSelesai = $jadwalItem->shift?->jam_selesai ?? '23:59:00';
|
||||||
|
|
||||||
|
$originalJamMulai = $jamMulai;
|
||||||
|
$originalJamSelesai = $jamSelesai;
|
||||||
|
|
||||||
|
$color = $this->getShiftColor($shiftName);
|
||||||
|
|
||||||
|
$title = ($jadwalItem->user?->nama_lengkap ?? 'Unknown') . "\n(" . $shiftName . ")";
|
||||||
|
$description = "Jam: " . substr($jamMulai, 0, 5) . " - " . substr($jamSelesai, 0, 5);
|
||||||
|
$isPoin = false;
|
||||||
|
$poinInfo = [];
|
||||||
|
|
||||||
|
if (isset($poinUsed[$key])) {
|
||||||
|
$isPoin = true;
|
||||||
|
$listPenggunaan = $poinUsed[$key];
|
||||||
|
|
||||||
|
$color = '#f6c23e';
|
||||||
|
|
||||||
|
foreach ($listPenggunaan as $penggunaan) {
|
||||||
|
$jenis = $penggunaan->jenisPengurangan?->nama_pengurangan ?? 'Unknown';
|
||||||
|
if ($penggunaan->id_pengurangan == 4 && $penggunaan->jam_masuk_custom) {
|
||||||
|
$jamMulai = substr($penggunaan->jam_masuk_custom, 0, 5) . ':00';
|
||||||
|
$description .= "\n\n⚠️ DATANG TELAT (Poin)\nJam Masuk Baru: $jamMulai";
|
||||||
|
$poinInfo[] = "⚠️ Datang Terlambat (Menjadi $jamMulai)";
|
||||||
|
} elseif ($penggunaan->id_pengurangan == 5 && $penggunaan->jam_pulang_custom) {
|
||||||
|
$jamSelesai = substr($penggunaan->jam_pulang_custom, 0, 5) . ':00';
|
||||||
|
$description .= "\n\n⚠️ PULANG CEPAT (Poin)\nJam Pulang Baru: $jamSelesai";
|
||||||
|
$poinInfo[] = "⚠️ Pulang Cepat (Menjadi $jamSelesai)";
|
||||||
|
} else {
|
||||||
|
$description .= "\n[INFO] " . $jenis;
|
||||||
|
$poinInfo[] = $jenis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$events[] = [
|
||||||
|
'id' => $jadwalItem->id_jadwal,
|
||||||
|
'title' => $title,
|
||||||
|
'start' => $jadwalItem->tanggal,
|
||||||
|
'backgroundColor' => $color,
|
||||||
|
'borderColor' => $color,
|
||||||
|
'extendedProps' => [
|
||||||
|
'description' => $description,
|
||||||
|
'is_poin' => $isPoin,
|
||||||
|
'is_holiday' => false,
|
||||||
|
'poin_info' => $poinInfo,
|
||||||
|
'nama_user' => $jadwalItem->user?->nama_lengkap ?? '-',
|
||||||
|
'nama_shift' => $shiftName,
|
||||||
|
'jam_mulai' => $jamMulai,
|
||||||
|
'jam_selesai' => $jamSelesai,
|
||||||
|
'original_jam_mulai' => $originalJamMulai,
|
||||||
|
'original_jam_selesai' => $originalJamSelesai,
|
||||||
|
'kantor' => $jadwalItem->user?->kantor?->nama_kantor ?? '-',
|
||||||
|
'jabatan' => $jadwalItem->user?->jabatan?->nama_jabatan ?? '-',
|
||||||
|
'id_shift' => $jadwalItem->id_shift,
|
||||||
|
'id_user' => $jadwalItem->id_user,
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$hariLibursQuery = \App\Models\HariLibur::whereBetween('tanggal', [$start, $end]);
|
||||||
|
if ($request->filled('filter_kantor') && $request->filter_kantor != "") {
|
||||||
|
$hariLibursQuery->where(function($q) use ($request) {
|
||||||
|
$q->whereNull('id_kantor')->orWhere('id_kantor', $request->filter_kantor);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
$hariLiburs = $hariLibursQuery->get();
|
||||||
|
|
||||||
|
foreach ($hariLiburs as $hl) {
|
||||||
|
$events[] = [
|
||||||
|
'id' => 'libur-' . $hl->id,
|
||||||
|
'title' => '🔴 ' . $hl->keterangan,
|
||||||
|
'start' => $hl->tanggal,
|
||||||
|
'backgroundColor' => '#ef4444',
|
||||||
|
'borderColor' => '#ef4444',
|
||||||
|
'display' => 'block',
|
||||||
|
'extendedProps' => [
|
||||||
|
'is_holiday' => true,
|
||||||
|
'is_poin' => false,
|
||||||
|
'keterangan' => $hl->keterangan,
|
||||||
|
'nama_user' => $hl->keterangan,
|
||||||
|
'nama_shift' => 'Hari Libur',
|
||||||
|
'jam_mulai' => '00:00',
|
||||||
|
'jam_selesai' => '00:00',
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json($events);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getShiftColor($namaShift)
|
||||||
|
{
|
||||||
|
if (stripos($namaShift, 'Pagi') !== false)
|
||||||
|
return '#10b981';
|
||||||
|
if (stripos($namaShift, 'Siang') !== false)
|
||||||
|
return '#3b82f6';
|
||||||
|
if (stripos($namaShift, 'Sore') !== false)
|
||||||
|
return '#f59e0b';
|
||||||
|
if (stripos($namaShift, 'Malam') !== false)
|
||||||
|
return '#6b7280';
|
||||||
|
return '#6366f1';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
$shifts = ShiftKerja::all();
|
||||||
|
$kantor = Kantor::all();
|
||||||
|
$divisi = Divisi::all();
|
||||||
|
|
||||||
|
$pegawai = User::where('status_aktif', 1)
|
||||||
|
->with(['kantor', 'jabatan'])
|
||||||
|
->orderBy('nama_lengkap', 'asc')
|
||||||
|
->get();
|
||||||
|
|
||||||
|
return view('jadwal.create', compact('shifts', 'pegawai', 'kantor', 'divisi'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'tanggal_mulai' => 'required|date',
|
||||||
|
'tanggal_selesai' => 'required|date|after_or_equal:tanggal_mulai',
|
||||||
|
'id_shift' => 'required|exists:shift_kerja,id_shift',
|
||||||
|
'user_ids' => 'required|array',
|
||||||
|
'user_ids.*' => 'exists:users,id',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$startDate = Carbon::parse($request->tanggal_mulai);
|
||||||
|
$endDate = Carbon::parse($request->tanggal_selesai);
|
||||||
|
$period = \Carbon\CarbonPeriod::create($startDate, $endDate);
|
||||||
|
|
||||||
|
$shiftId = $request->id_shift;
|
||||||
|
$userIds = $request->user_ids;
|
||||||
|
|
||||||
|
$count = 0;
|
||||||
|
$refundCount = 0;
|
||||||
|
$poinService = new PoinService();
|
||||||
|
|
||||||
|
$usersData = \App\Models\User::whereIn('id', $userIds)->get(['id', 'id_kantor'])->keyBy('id');
|
||||||
|
|
||||||
|
try {
|
||||||
|
DB::transaction(function () use ($period, $userIds, $shiftId, &$count, &$refundCount, $poinService, $usersData) {
|
||||||
|
foreach ($period as $date) {
|
||||||
|
$dateStr = $date->format('Y-m-d');
|
||||||
|
$libursDate = \App\Models\HariLibur::where('tanggal', $dateStr)->get();
|
||||||
|
|
||||||
|
foreach ($userIds as $userId) {
|
||||||
|
$user = $usersData->get($userId);
|
||||||
|
$isLibur = $libursDate->contains(function($libur) use ($user) {
|
||||||
|
return is_null($libur->id_kantor) || ($user && $libur->id_kantor == $user->id_kantor);
|
||||||
|
});
|
||||||
|
|
||||||
|
if ($isLibur) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$conflictPoin = PenggunaanPoin::where('id_user', $userId)
|
||||||
|
->where('tanggal_penggunaan', $dateStr)
|
||||||
|
->where('id_status', 2)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if ($conflictPoin) {
|
||||||
|
$poinService->refundPoin($conflictPoin->id_penggunaan);
|
||||||
|
$refundCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
JadwalKerja::updateOrCreate(
|
||||||
|
['id_user' => $userId, 'tanggal' => $dateStr],
|
||||||
|
['id_shift' => $shiftId]
|
||||||
|
);
|
||||||
|
$count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$message = "Berhasil memproses $count jadwal kerja!";
|
||||||
|
if ($refundCount > 0) {
|
||||||
|
$message .= " ⚠️ PERINGATAN: $refundCount penggunaan poin dibatalkan otomatis & saldo dikembalikan karena konflik jadwal.";
|
||||||
|
return redirect()->route('jadwal.index')->with('warning', $message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->route('jadwal.index')->with('success', $message);
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return redirect()->back()->with('error', 'Terjadi kesalahan: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(Request $request, $id)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'id_shift' => 'required|exists:shift_kerja,id_shift',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$jadwal = JadwalKerja::findOrFail($id);
|
||||||
|
$warningMsg = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
DB::transaction(function () use ($jadwal, $request, &$warningMsg) {
|
||||||
|
$conflictPoin = PenggunaanPoin::where('id_user', $jadwal->id_user)
|
||||||
|
->where('tanggal_penggunaan', $jadwal->tanggal)
|
||||||
|
->where('id_status', 2)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if ($conflictPoin) {
|
||||||
|
$poinService = new PoinService();
|
||||||
|
$poinService->refundPoin($conflictPoin->id_penggunaan);
|
||||||
|
$warningMsg = "Jadwal diperbarui, namun penggunaan poin user pada tanggal ini telah DIBATALKAN otomatis.";
|
||||||
|
}
|
||||||
|
|
||||||
|
$jadwal->update(['id_shift' => $request->id_shift]);
|
||||||
|
});
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true,
|
||||||
|
'message' => $warningMsg ?? 'Jadwal berhasil diperbarui'
|
||||||
|
]);
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy($id)
|
||||||
|
{
|
||||||
|
$jadwal = JadwalKerja::findOrFail($id);
|
||||||
|
$jadwal->delete();
|
||||||
|
|
||||||
|
return response()->json(['success' => true, 'message' => 'Jadwal berhasil dihapus']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function bulkDestroy(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'tanggal_mulai' => 'required|date',
|
||||||
|
'tanggal_selesai' => 'required|date|after_or_equal:tanggal_mulai',
|
||||||
|
'user_ids' => 'required|array',
|
||||||
|
'user_ids.*' => 'exists:users,id',
|
||||||
|
]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
DB::transaction(function () use ($request) {
|
||||||
|
JadwalKerja::whereIn('id_user', $request->user_ids)
|
||||||
|
->whereBetween('tanggal', [$request->tanggal_mulai, $request->tanggal_selesai])
|
||||||
|
->delete();
|
||||||
|
});
|
||||||
|
|
||||||
|
return redirect()->back()->with('success', 'Jadwal kerja berhasil dihapus pada rentang tanggal tersebut.');
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return redirect()->back()->with('error', 'Terjadi kesalahan saat menghapus jadwal: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function checkConflicts(Request $request)
|
||||||
|
{
|
||||||
|
$userIds = $request->user_ids;
|
||||||
|
$startDate = $request->tanggal_mulai;
|
||||||
|
$endDate = $request->tanggal_selesai;
|
||||||
|
|
||||||
|
if (empty($userIds) || !$startDate || !$endDate) {
|
||||||
|
return response()->json(['has_conflict' => false]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$conflicts = PenggunaanPoin::with('user')
|
||||||
|
->whereIn('id_user', $userIds)
|
||||||
|
->whereBetween('tanggal_penggunaan', [$startDate, $endDate])
|
||||||
|
->where('id_status', 2)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
if ($conflicts->count() > 0) {
|
||||||
|
$details = $conflicts->map(function ($item) {
|
||||||
|
return "- " . $item->user->nama_lengkap . " (" . date('d M Y', strtotime($item->tanggal_penggunaan)) . ")";
|
||||||
|
})->join('<br>');
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'has_conflict' => true,
|
||||||
|
'message' => "Ditemukan <b>{$conflicts->count()} karyawan</b> yang sedang menggunakan Poin (Cuti/Pulang Cepat) pada tanggal ini:<br><br><small>$details</small><br><br>Jika dilanjutkan, <b>Penggunaan Poin akan DIBATALKAN otomatis</b> dan saldo dikembalikan."
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json(['has_conflict' => false]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\Kantor;
|
||||||
|
use App\Http\Requests\StoreKantorRequest;
|
||||||
|
use App\Http\Requests\UpdateKantorRequest;
|
||||||
|
|
||||||
|
class KantorController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$kantor = Kantor::latest()->paginate(10);
|
||||||
|
return view('kantor.index', compact('kantor'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(StoreKantorRequest $request)
|
||||||
|
{
|
||||||
|
Kantor::create($request->validated());
|
||||||
|
return redirect()->back()->with('success', 'Lokasi kantor berhasil ditambahkan.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(UpdateKantorRequest $request, $id)
|
||||||
|
{
|
||||||
|
$kantor = Kantor::findOrFail($id);
|
||||||
|
$kantor->update($request->validated());
|
||||||
|
return redirect()->back()->with('success', 'Data kantor berhasil diperbarui.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy($id)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Kantor::findOrFail($id)->delete();
|
||||||
|
return redirect()->back()->with('success', 'Data kantor berhasil dihapus.');
|
||||||
|
} catch (\Illuminate\Database\QueryException $e) {
|
||||||
|
if ($e->getCode() === '23000') {
|
||||||
|
return redirect()->back()->with('error', 'Kantor tidak bisa dihapus karena masih digunakan oleh data pegawai.');
|
||||||
|
}
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,144 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Models\Presensi;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Maatwebsite\Excel\Facades\Excel;
|
||||||
|
use App\Exports\LaporanPresensiExport;
|
||||||
|
use Barryvdh\DomPDF\Facade\Pdf;
|
||||||
|
|
||||||
|
class LaporanController extends Controller
|
||||||
|
{
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$bulan = $request->input('bulan', date('m'));
|
||||||
|
$tahun = $request->input('tahun', date('Y'));
|
||||||
|
$divisiId = $request->input('id_divisi');
|
||||||
|
|
||||||
|
$rekap = $this->buildRekap($bulan, $tahun, $divisiId);
|
||||||
|
$divisiList = \App\Models\Divisi::all();
|
||||||
|
|
||||||
|
return view('laporan.index', compact('rekap', 'bulan', 'tahun', 'divisiList', 'divisiId'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function cuti(Request $request)
|
||||||
|
{
|
||||||
|
$bulan = $request->input('bulan', date('m'));
|
||||||
|
$tahun = $request->input('tahun', date('Y'));
|
||||||
|
$search = $request->input('search');
|
||||||
|
$divisiId = $request->input('id_divisi');
|
||||||
|
|
||||||
|
$query = \App\Models\PengajuanIzin::with(['user.divisi', 'jenisIzin'])
|
||||||
|
->whereYear('tanggal_mulai', $tahun)
|
||||||
|
->whereMonth('tanggal_mulai', $bulan);
|
||||||
|
|
||||||
|
if ($search) {
|
||||||
|
$query->whereHas('user', function($q) use ($search) {
|
||||||
|
$q->where('nama_lengkap', 'like', "%{$search}%")
|
||||||
|
->orWhere('nik', 'like', "%{$search}%");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($divisiId) {
|
||||||
|
$query->whereHas('user', function($q) use ($divisiId) {
|
||||||
|
$q->where('id_divisi', $divisiId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$izinList = $query->orderBy('tanggal_mulai', 'desc')->paginate(15)->withQueryString();
|
||||||
|
$divisiList = \App\Models\Divisi::all();
|
||||||
|
|
||||||
|
return view('laporan.izin', compact('izinList', 'bulan', 'tahun', 'search', 'divisiId', 'divisiList'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function exportExcel(Request $request)
|
||||||
|
{
|
||||||
|
$bulan = $request->input('bulan', date('m'));
|
||||||
|
$tahun = $request->input('tahun', date('Y'));
|
||||||
|
$divisiId = $request->input('id_divisi');
|
||||||
|
|
||||||
|
$rekap = $this->buildRekap($bulan, $tahun, $divisiId);
|
||||||
|
|
||||||
|
$filename = "Laporan_Presensi_{$bulan}_{$tahun}.xlsx";
|
||||||
|
|
||||||
|
return Excel::download(new LaporanPresensiExport($rekap, $bulan, $tahun), $filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function exportPdf(Request $request)
|
||||||
|
{
|
||||||
|
$bulan = $request->input('bulan', date('m'));
|
||||||
|
$tahun = $request->input('tahun', date('Y'));
|
||||||
|
$divisiId = $request->input('id_divisi');
|
||||||
|
|
||||||
|
$rekap = $this->buildRekap($bulan, $tahun, $divisiId);
|
||||||
|
|
||||||
|
$pdf = Pdf::loadView('laporan.pdf', compact('rekap', 'bulan', 'tahun'));
|
||||||
|
$pdf->setPaper('a4', 'landscape');
|
||||||
|
|
||||||
|
return $pdf->download("Laporan_Presensi_{$bulan}_{$tahun}.pdf");
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildRekap(int $bulan, int $tahun, $divisiId = null): array
|
||||||
|
{
|
||||||
|
|
||||||
|
$idTepatWaktu = 1;
|
||||||
|
$idTerlambat = 2;
|
||||||
|
$idIzin = 3;
|
||||||
|
$idSakit = 4;
|
||||||
|
$idAlpha = 5;
|
||||||
|
|
||||||
|
$pegawaiQuery = User::with(['jabatan', 'divisi'])
|
||||||
|
->where('status_aktif', 1)
|
||||||
|
->select('id', 'nama_lengkap', 'nik', 'id_jabatan', 'id_divisi')
|
||||||
|
->orderBy('nama_lengkap', 'asc');
|
||||||
|
|
||||||
|
if ($divisiId) {
|
||||||
|
$pegawaiQuery->where('id_divisi', $divisiId);
|
||||||
|
}
|
||||||
|
|
||||||
|
$pegawai = $pegawaiQuery->get();
|
||||||
|
|
||||||
|
$presensiStats = Presensi::whereMonth('tanggal', $bulan)
|
||||||
|
->whereYear('tanggal', $tahun)
|
||||||
|
->selectRaw("
|
||||||
|
id_user,
|
||||||
|
SUM(CASE WHEN id_status IN (?, ?) THEN 1 ELSE 0 END) as hadir,
|
||||||
|
SUM(CASE WHEN id_status = ? THEN 1 ELSE 0 END) as terlambat,
|
||||||
|
SUM(CASE WHEN id_status = ? THEN 1 ELSE 0 END) as alpha,
|
||||||
|
SUM(CASE WHEN id_status = ? THEN 1 ELSE 0 END) as izin,
|
||||||
|
SUM(CASE WHEN id_status = ? THEN 1 ELSE 0 END) as sakit
|
||||||
|
", [$idTepatWaktu, $idTerlambat, $idTerlambat, $idAlpha, $idIzin, $idSakit])
|
||||||
|
->groupBy('id_user')
|
||||||
|
->get()
|
||||||
|
->keyBy('id_user');
|
||||||
|
|
||||||
|
$poinStats = DB::table('poin_lembur')
|
||||||
|
->whereMonth('tanggal', $bulan)
|
||||||
|
->whereYear('tanggal', $tahun)
|
||||||
|
->selectRaw('id_user, SUM(jumlah_poin) as total_poin')
|
||||||
|
->groupBy('id_user')
|
||||||
|
->pluck('total_poin', 'id_user');
|
||||||
|
|
||||||
|
$rekap = [];
|
||||||
|
|
||||||
|
foreach ($pegawai as $p) {
|
||||||
|
$stats = $presensiStats->get($p->id);
|
||||||
|
|
||||||
|
$rekap[] = [
|
||||||
|
'user' => $p,
|
||||||
|
'hadir' => $stats->hadir ?? 0,
|
||||||
|
'terlambat' => $stats->terlambat ?? 0,
|
||||||
|
'alpha' => $stats->alpha ?? 0,
|
||||||
|
'izin' => $stats->izin ?? 0,
|
||||||
|
'sakit' => $stats->sakit ?? 0,
|
||||||
|
'poin_lembur' => $poinStats->get($p->id, 0)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $rekap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,102 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Models\Lembur;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Maatwebsite\Excel\Facades\Excel;
|
||||||
|
use App\Exports\LaporanLemburExport;
|
||||||
|
|
||||||
|
class LaporanLemburController extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$bulan = $request->input('bulan', date('m'));
|
||||||
|
$tahun = $request->input('tahun', date('Y'));
|
||||||
|
$search = $request->input('search');
|
||||||
|
$divisiId = $request->input('id_divisi');
|
||||||
|
|
||||||
|
$query = User::with(['divisi', 'jabatan', 'lemburs' => function($q) use ($bulan, $tahun) {
|
||||||
|
$q->whereYear('tanggal_lembur', $tahun)
|
||||||
|
->whereMonth('tanggal_lembur', $bulan)
|
||||||
|
->where('id_status', 2);
|
||||||
|
}])
|
||||||
|
->whereHas('roles', function($q) {
|
||||||
|
$q->where('nama_role', '!=', 'super_admin');
|
||||||
|
});
|
||||||
|
|
||||||
|
if ($search) {
|
||||||
|
$query->where(function($q) use ($search) {
|
||||||
|
$q->where('nama_lengkap', 'like', '%' . $search . '%')
|
||||||
|
->orWhere('nik', 'like', '%' . $search . '%');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($divisiId) {
|
||||||
|
$query->where('id_divisi', $divisiId);
|
||||||
|
}
|
||||||
|
|
||||||
|
$pegawai = $query->orderBy('nama_lengkap', 'asc')->paginate(15)->withQueryString();
|
||||||
|
$divisiList = \App\Models\Divisi::all();
|
||||||
|
|
||||||
|
$rekap = [];
|
||||||
|
foreach ($pegawai as $p) {
|
||||||
|
$totalMenit = $p->lemburs->sum('durasi_menit');
|
||||||
|
$jam = floor($totalMenit / 60);
|
||||||
|
$menit = $totalMenit % 60;
|
||||||
|
|
||||||
|
$rekap[$p->id] = [
|
||||||
|
'total_menit' => $totalMenit,
|
||||||
|
'format_jam' => "{$jam}j {$menit}m",
|
||||||
|
'jumlah_hari' => $p->lemburs->count(),
|
||||||
|
'poin_diperoleh' => $totalMenit,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('laporan-lembur.index', compact('pegawai', 'rekap', 'bulan', 'tahun', 'search', 'divisiId', 'divisiList'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function exportExcel(Request $request)
|
||||||
|
{
|
||||||
|
$bulan = $request->input('bulan', date('m'));
|
||||||
|
$tahun = $request->input('tahun', date('Y'));
|
||||||
|
$divisiId = $request->input('id_divisi');
|
||||||
|
|
||||||
|
$query = User::with(['divisi', 'jabatan', 'lemburs' => function($q) use ($bulan, $tahun) {
|
||||||
|
$q->whereYear('tanggal_lembur', $tahun)
|
||||||
|
->whereMonth('tanggal_lembur', $bulan)
|
||||||
|
->where('id_status', 2);
|
||||||
|
}])
|
||||||
|
->whereHas('roles', function($q) {
|
||||||
|
$q->where('nama_role', '!=', 'super_admin');
|
||||||
|
});
|
||||||
|
|
||||||
|
if ($divisiId) {
|
||||||
|
$query->where('id_divisi', $divisiId);
|
||||||
|
}
|
||||||
|
|
||||||
|
$pegawai = $query->orderBy('nama_lengkap', 'asc')->get();
|
||||||
|
|
||||||
|
$rekap = [];
|
||||||
|
foreach ($pegawai as $p) {
|
||||||
|
$totalMenit = $p->lemburs->sum('durasi_menit');
|
||||||
|
$jam = floor($totalMenit / 60);
|
||||||
|
$menit = $totalMenit % 60;
|
||||||
|
|
||||||
|
$rekap[$p->id] = [
|
||||||
|
'total_menit' => $totalMenit,
|
||||||
|
'format_jam' => "{$jam}j {$menit}m",
|
||||||
|
'jumlah_hari' => $p->lemburs->count(),
|
||||||
|
'poin_diperoleh' => $totalMenit,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$filename = "Laporan_Lembur_{$bulan}_{$tahun}.xlsx";
|
||||||
|
|
||||||
|
return Excel::download(new LaporanLemburExport($pegawai, $rekap, $bulan, $tahun), $filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,87 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\Lembur;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Models\JenisKompensasi;
|
||||||
|
use App\Services\LemburService;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
|
class LemburController extends Controller
|
||||||
|
{
|
||||||
|
protected $lemburService;
|
||||||
|
|
||||||
|
public function __construct(LemburService $lemburService)
|
||||||
|
{
|
||||||
|
$this->lemburService = $lemburService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$lembur = Lembur::with(['user', 'status', 'kompensasi'])
|
||||||
|
->orderByRaw("CASE WHEN id_status = 1 THEN 0 ELSE 1 END")
|
||||||
|
->orderBy('created_at', 'desc')
|
||||||
|
->paginate(10);
|
||||||
|
|
||||||
|
return view('lembur.index', compact('lembur'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
$pegawai = User::where('status_aktif', 1)->orderBy('nama_lengkap', 'asc')->get();
|
||||||
|
$kompensasi = JenisKompensasi::all();
|
||||||
|
return view('lembur.create', compact('pegawai', 'kompensasi'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'id_user' => 'required|exists:users,id',
|
||||||
|
'tanggal_lembur' => 'required|date',
|
||||||
|
'jam_mulai' => 'required',
|
||||||
|
'jam_selesai' => 'required',
|
||||||
|
'id_kompensasi' => 'required|exists:jenis_kompensasi,id_kompensasi',
|
||||||
|
'keterangan' => 'nullable|string'
|
||||||
|
]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
DB::transaction(function () use ($request) {
|
||||||
|
$user = User::findOrFail($request->id_user);
|
||||||
|
$lembur = $this->lemburService->createLembur($user, $request->all());
|
||||||
|
$this->lemburService->approve($lembur);
|
||||||
|
});
|
||||||
|
|
||||||
|
return redirect()->route('lembur.index')->with('success', 'Data lembur manual berhasil ditambahkan dan disetujui otomatis.');
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return redirect()->back()->with('error', 'Gagal menambahkan lembur: ' . $e->getMessage())->withInput();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(Request $request, Lembur $lembur)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'action' => 'required|in:approve,reject',
|
||||||
|
'alasan_penolakan' => 'required_if:action,reject|nullable|string'
|
||||||
|
]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if ($request->action == 'approve') {
|
||||||
|
$this->lemburService->approve($lembur);
|
||||||
|
$message = 'Pengajuan lembur berhasil disetujui.';
|
||||||
|
|
||||||
|
if ($lembur->id_kompensasi == 2) {
|
||||||
|
$message .= ' Poin telah ditambahkan ke karyawan.';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->lemburService->reject($lembur, $request->alasan_penolakan);
|
||||||
|
$message = 'Pengajuan lembur berhasil ditolak.';
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->back()->with('success', $message);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return redirect()->back()->with('error', 'Gagal memproses pengajuan: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,186 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Models\Divisi;
|
||||||
|
use App\Models\Jabatan;
|
||||||
|
use App\Models\Kantor;
|
||||||
|
use App\Models\Role;
|
||||||
|
use App\Http\Requests\StorePegawaiRequest;
|
||||||
|
use App\Http\Requests\UpdatePegawaiRequest;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
|
class PegawaiController extends Controller
|
||||||
|
{
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$query = User::with(['divisi', 'jabatan', 'kantor', 'roles'])
|
||||||
|
->whereDoesntHave('roles', function ($q) {
|
||||||
|
$q->where('nama_role', 'admin');
|
||||||
|
});
|
||||||
|
|
||||||
|
if ($request->filled('filter_jabatan')) {
|
||||||
|
$query->where('id_jabatan', $request->filter_jabatan);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->filled('filter_kantor')) {
|
||||||
|
$query->where('id_kantor', $request->filter_kantor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->filled('filter_status')) {
|
||||||
|
$status = $request->filter_status == 'active' ? 1 : 0;
|
||||||
|
$query->where('status_aktif', $status);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->filled('search')) {
|
||||||
|
$search = $request->search;
|
||||||
|
$query->where(function ($q) use ($search) {
|
||||||
|
$q->where('nama_lengkap', 'like', "%{$search}%")
|
||||||
|
->orWhere('email', 'like', "%{$search}%")
|
||||||
|
->orWhere('nik', 'like', "%{$search}%");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$pegawai = $query->latest()->paginate(10)->withQueryString();
|
||||||
|
|
||||||
|
$allKantor = Kantor::withCount([
|
||||||
|
'users as total_pegawai' => function ($q) {
|
||||||
|
$q->whereDoesntHave('roles', function ($sq) {
|
||||||
|
$sq->where('nama_role', 'admin');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
])->get();
|
||||||
|
|
||||||
|
$stats = [
|
||||||
|
'kantor_list' => $allKantor,
|
||||||
|
'total' => User::whereDoesntHave('roles', function ($q) {
|
||||||
|
$q->where('nama_role', 'admin');
|
||||||
|
})->count(),
|
||||||
|
'active' => User::where('status_aktif', 1)
|
||||||
|
->whereDoesntHave('roles', function ($q) {
|
||||||
|
$q->where('nama_role', 'admin');
|
||||||
|
})->count(),
|
||||||
|
];
|
||||||
|
|
||||||
|
$allJabatan = Jabatan::all();
|
||||||
|
|
||||||
|
return view('pegawai.index', compact('pegawai', 'stats', 'allJabatan', 'allKantor'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(StorePegawaiRequest $request)
|
||||||
|
{
|
||||||
|
$data = $request->validated();
|
||||||
|
|
||||||
|
if ($request->hasFile('foto')) {
|
||||||
|
$data['foto'] = $request->file('foto')->store('foto-profil', 'public');
|
||||||
|
}
|
||||||
|
|
||||||
|
$data['password'] = Hash::make('Mpg123!');
|
||||||
|
$data['status_aktif'] = 1;
|
||||||
|
$data['sisa_cuti'] = 12;
|
||||||
|
|
||||||
|
$user = User::create($data);
|
||||||
|
|
||||||
|
if ($request->filled('id_role')) {
|
||||||
|
$user->roles()->attach($request->id_role);
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->route('pegawai.index')->with('success', 'Pegawai baru berhasil ditambahkan.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(UpdatePegawaiRequest $request, $id)
|
||||||
|
{
|
||||||
|
$pegawai = User::findOrFail($id);
|
||||||
|
$data = $request->validated();
|
||||||
|
|
||||||
|
if ($request->hasFile('foto')) {
|
||||||
|
if ($pegawai->foto) {
|
||||||
|
Storage::disk('public')->delete($pegawai->foto);
|
||||||
|
}
|
||||||
|
$data['foto'] = $request->file('foto')->store('foto-profil', 'public');
|
||||||
|
}
|
||||||
|
|
||||||
|
$pegawai->update($data);
|
||||||
|
|
||||||
|
if ($request->filled('id_role')) {
|
||||||
|
$pegawai->roles()->sync([$request->id_role]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->route('pegawai.index')->with('success', 'Data pegawai berhasil diperbarui.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
$divisi = Divisi::all();
|
||||||
|
$jabatan = Jabatan::all();
|
||||||
|
$kantor = Kantor::all();
|
||||||
|
$roles = Role::all();
|
||||||
|
return view('pegawai.create', compact('divisi', 'jabatan', 'kantor', 'roles'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function show($id)
|
||||||
|
{
|
||||||
|
$pegawai = User::with(['divisi', 'jabatan', 'kantor', 'roles'])->findOrFail($id);
|
||||||
|
|
||||||
|
$sisaPoin = \App\Models\PoinLembur::where('id_user', $id)
|
||||||
|
->where('is_fully_used', false)
|
||||||
|
->whereDate('expired_at', '>=', now()->toDateString())
|
||||||
|
->sum('sisa_poin');
|
||||||
|
|
||||||
|
$historyTambah = \App\Models\PoinLembur::where('id_user', $id)
|
||||||
|
->select('id_poin as id', 'tanggal', 'jumlah_poin as jumlah', 'keterangan', \DB::raw("'penambahan' as tipe"))
|
||||||
|
->orderBy('tanggal', 'desc')
|
||||||
|
->take(10)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
$historyKurang = \App\Models\PenggunaanPoin::where('id_user', $id)
|
||||||
|
->where('id_status', 1)
|
||||||
|
->select('id_penggunaan as id', 'tanggal_penggunaan as tanggal', 'jumlah_poin as jumlah', \DB::raw("'Penggunaan Poin' as keterangan"), \DB::raw("'pengurangan' as tipe"))
|
||||||
|
->orderBy('tanggal_penggunaan', 'desc')
|
||||||
|
->take(10)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
$historyPoin = $historyTambah->concat($historyKurang)->sortByDesc('tanggal')->take(10);
|
||||||
|
|
||||||
|
$riwayatPresensi = \App\Models\Presensi::with(['status', 'jadwal.shift'])
|
||||||
|
->where('id_user', $id)
|
||||||
|
->whereDate('tanggal', '>=', now()->subDays(30)->toDateString())
|
||||||
|
->orderBy('tanggal', 'desc')
|
||||||
|
->get();
|
||||||
|
|
||||||
|
$riwayatIzin = \App\Models\PengajuanIzin::with('jenisIzin')
|
||||||
|
->where('id_user', $id)
|
||||||
|
->whereDate('tanggal_mulai', '>=', now()->subDays(30)->toDateString())
|
||||||
|
->orderBy('tanggal_mulai', 'desc')
|
||||||
|
->get();
|
||||||
|
|
||||||
|
return view('pegawai.show', compact('pegawai', 'sisaPoin', 'historyPoin', 'riwayatPresensi', 'riwayatIzin'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit($id)
|
||||||
|
{
|
||||||
|
$pegawai = User::findOrFail($id);
|
||||||
|
$divisi = Divisi::all();
|
||||||
|
$jabatan = Jabatan::all();
|
||||||
|
$kantor = Kantor::all();
|
||||||
|
$roles = Role::all();
|
||||||
|
return view('pegawai.edit', compact('pegawai', 'divisi', 'jabatan', 'kantor', 'roles'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy($id)
|
||||||
|
{
|
||||||
|
$pegawai = User::findOrFail($id);
|
||||||
|
|
||||||
|
if ($pegawai->status_aktif == 0) {
|
||||||
|
$pegawai->delete();
|
||||||
|
return redirect()->route('pegawai.index')->with('success', 'Data pegawai berhasil dihapus (Soft Delete).');
|
||||||
|
}
|
||||||
|
|
||||||
|
$pegawai->update(['status_aktif' => 0]);
|
||||||
|
|
||||||
|
return redirect()->route('pegawai.index')->with('success', 'Status pegawai telah diubah menjadi Non-Aktif (Resigned). Histori data tetap tersimpan.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,197 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\PengajuanIzin;
|
||||||
|
use App\Models\Presensi;
|
||||||
|
use App\Models\JenisIzin;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Models\SuratIzin;
|
||||||
|
use App\Models\TandaTangan;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
|
||||||
|
class PengajuanIzinController extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$statusId = $request->get('status');
|
||||||
|
|
||||||
|
$query = PengajuanIzin::with(['user', 'jenisIzin', 'statusPengajuan', 'suratIzin']);
|
||||||
|
|
||||||
|
if ($statusId) {
|
||||||
|
$query->where('id_status', $statusId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->has('search') && $request->search != '') {
|
||||||
|
$query->whereHas('user', function ($q) use ($request) {
|
||||||
|
$q->where('nama_lengkap', 'like', '%' . $request->search . '%');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$izin = $query->orderBy('created_at', 'desc')->paginate(15);
|
||||||
|
|
||||||
|
$statuses = \App\Models\StatusPengajuan::all();
|
||||||
|
$jenisIzin = \App\Models\JenisIzin::all();
|
||||||
|
$users = \App\Models\User::with(['kantor', 'divisi', 'jabatan'])->select('id', 'nama_lengkap', 'nik', 'id_kantor', 'id_divisi', 'id_jabatan')->orderBy('nama_lengkap', 'asc')->get();
|
||||||
|
$kantor = \App\Models\Kantor::all();
|
||||||
|
$divisi = \App\Models\Divisi::all();
|
||||||
|
|
||||||
|
return view('izin.index', compact('izin', 'statusId', 'statuses', 'jenisIzin', 'users', 'kantor', 'divisi'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'id_user' => 'required|exists:users,id',
|
||||||
|
'id_jenis_izin' => 'required|exists:jenis_izin,id_jenis_izin',
|
||||||
|
'tanggal_mulai' => 'required|date',
|
||||||
|
'tanggal_selesai' => 'required|date|after_or_equal:tanggal_mulai',
|
||||||
|
'alasan' => 'required|string',
|
||||||
|
'bukti_file' => 'required|image|mimes:jpeg,png,jpg,pdf|max:2048'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$jenisIzin = JenisIzin::find($request->id_jenis_izin);
|
||||||
|
if ($jenisIzin && $jenisIzin->nama_izin == 'Cuti') {
|
||||||
|
$diffParams = Carbon::parse($request->tanggal_mulai, 'Asia/Jakarta')->diffInDays(Carbon::now('Asia/Jakarta'));
|
||||||
|
|
||||||
|
if (Carbon::parse($request->tanggal_mulai, 'Asia/Jakarta')->diffInDays(Carbon::now('Asia/Jakarta')) < 7) {
|
||||||
|
return back()->with('error', 'Pengajuan Cuti minimal H-7!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
DB::beginTransaction();
|
||||||
|
|
||||||
|
$path = null;
|
||||||
|
if ($request->hasFile('bukti_file')) {
|
||||||
|
$path = $request->file('bukti_file')->store('uploads/izin', 'public');
|
||||||
|
}
|
||||||
|
|
||||||
|
$izin = PengajuanIzin::create([
|
||||||
|
'id_user' => $request->id_user,
|
||||||
|
'id_jenis_izin' => $request->id_jenis_izin,
|
||||||
|
'tanggal_mulai' => $request->tanggal_mulai,
|
||||||
|
'tanggal_selesai' => $request->tanggal_selesai,
|
||||||
|
'alasan' => $request->alasan,
|
||||||
|
'bukti_file' => $path,
|
||||||
|
'id_status' => 1
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($izin->id_jenis_izin == 2) {
|
||||||
|
$user = User::with(['jabatan', 'divisi'])->find($request->id_user);
|
||||||
|
$ttdAktif = TandaTangan::where('id_user', $user->id)->active()->first();
|
||||||
|
$tglMulai = Carbon::parse($request->tanggal_mulai)->translatedFormat('d F Y');
|
||||||
|
$tglSelesai = Carbon::parse($request->tanggal_selesai)->translatedFormat('d F Y');
|
||||||
|
|
||||||
|
$isiSurat = "Dengan hormat,\n\n"
|
||||||
|
. "Saya yang bertanda tangan di bawah ini:\n"
|
||||||
|
. "Nama: {$user->nama_lengkap}\n"
|
||||||
|
. "NIK: {$user->nik}\n"
|
||||||
|
. "Jabatan: " . ($user->jabatan->nama_jabatan ?? '-') . "\n"
|
||||||
|
. "Divisi: " . ($user->divisi->nama_divisi ?? '-') . "\n\n"
|
||||||
|
. "Dengan ini mengajukan Cuti mulai tanggal {$tglMulai} sampai dengan {$tglSelesai}.\n\n"
|
||||||
|
. "Alasan: {$request->alasan}\n\n"
|
||||||
|
. "Demikian surat ini saya buat dengan sebenar-benarnya. "
|
||||||
|
. "Atas perhatian dan persetujuannya, saya ucapkan terima kasih.";
|
||||||
|
|
||||||
|
SuratIzin::create([
|
||||||
|
'id_izin' => $izin->id_izin,
|
||||||
|
'id_user' => $user->id,
|
||||||
|
'id_ttd_pengaju' => $ttdAktif?->id_tanda_tangan,
|
||||||
|
'isi_surat' => $isiSurat,
|
||||||
|
'status_surat' => 'menunggu_manajer',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
DB::commit();
|
||||||
|
return redirect()->back()->with('success', 'Pengajuan izin berhasil dibuat.');
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
DB::rollBack();
|
||||||
|
return redirect()->back()->with('error', 'Gagal membuat izin: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function approve($id)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
DB::beginTransaction();
|
||||||
|
|
||||||
|
$izin = PengajuanIzin::with('jenisIzin')->findOrFail($id);
|
||||||
|
|
||||||
|
if ($izin->id_status !== 1) {
|
||||||
|
return redirect()->back()->with('error', 'Pengajuan ini sudah diproses sebelumnya.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($izin->id_jenis_izin == 2) {
|
||||||
|
return redirect()->back()->with('error', 'Pengajuan Cuti harus disetujui melalui menu Surat Izin (Manajer → HRD).');
|
||||||
|
}
|
||||||
|
|
||||||
|
$izin->update(['id_status' => 2]);
|
||||||
|
|
||||||
|
$statusPresensiId = 3;
|
||||||
|
if ($izin->id_jenis_izin == 1) {
|
||||||
|
$statusPresensiId = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
$startDate = Carbon::parse($izin->tanggal_mulai, 'Asia/Jakarta');
|
||||||
|
$endDate = Carbon::parse($izin->tanggal_selesai, 'Asia/Jakarta');
|
||||||
|
|
||||||
|
while ($startDate->lte($endDate)) {
|
||||||
|
$tanggal = $startDate->format('Y-m-d');
|
||||||
|
|
||||||
|
Presensi::updateOrCreate(
|
||||||
|
[
|
||||||
|
'id_user' => $izin->id_user,
|
||||||
|
'tanggal' => $tanggal
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'id_status' => $statusPresensiId,
|
||||||
|
'jam_masuk' => null,
|
||||||
|
'jam_pulang' => null,
|
||||||
|
'id_validasi' => 1,
|
||||||
|
'alasan_telat' => $izin->jenisIzin->nama_izin . ': ' . $izin->alasan
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$startDate->addDay();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($izin->id_jenis_izin == 2) {
|
||||||
|
$user = \App\Models\User::find($izin->id_user);
|
||||||
|
$jumlahHari = Carbon::parse($izin->tanggal_mulai)->diffInDays(Carbon::parse($izin->tanggal_selesai)) + 1;
|
||||||
|
$user->decrement('sisa_cuti', $jumlahHari);
|
||||||
|
}
|
||||||
|
|
||||||
|
DB::commit();
|
||||||
|
return redirect()->back()->with('success', 'Izin disetujui & data presensi diperbarui.');
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
DB::rollBack();
|
||||||
|
return redirect()->back()->with('error', 'Gagal: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function reject(Request $request, $id)
|
||||||
|
{
|
||||||
|
$izin = PengajuanIzin::findOrFail($id);
|
||||||
|
|
||||||
|
if ($izin->id_status !== 1) {
|
||||||
|
return redirect()->back()->with('error', 'Pengajuan ini sudah diproses sebelumnya.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($izin->id_jenis_izin == 2) {
|
||||||
|
return redirect()->back()->with('error', 'Pengajuan Cuti harus ditolak melalui menu Surat Izin.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$izin->update([
|
||||||
|
'id_status' => 3
|
||||||
|
]);
|
||||||
|
|
||||||
|
return redirect()->back()->with('success', 'Pengajuan izin berhasil ditolak.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\PenggunaanPoin;
|
||||||
|
use App\Services\PoinService;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
|
class PenggunaanPoinController extends Controller
|
||||||
|
{
|
||||||
|
protected $poinService;
|
||||||
|
|
||||||
|
public function __construct(PoinService $poinService)
|
||||||
|
{
|
||||||
|
$this->poinService = $poinService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$penggunaan = PenggunaanPoin::with(['user', 'jenisPengurangan', 'status'])
|
||||||
|
->orderByRaw("CASE WHEN id_status = 1 THEN 0 ELSE 1 END")
|
||||||
|
->orderBy('tanggal_diajukan', 'desc')
|
||||||
|
->paginate(10);
|
||||||
|
|
||||||
|
return view('penggunaan-poin.index', compact('penggunaan'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(Request $request, $id)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'action' => 'required|in:approve,reject',
|
||||||
|
'alasan_penolakan' => 'required_if:action,reject|nullable|string'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$penggunaan = PenggunaanPoin::findOrFail($id);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if ($request->action == 'approve') {
|
||||||
|
DB::transaction(function () use ($penggunaan) {
|
||||||
|
$penggunaan->update(['id_status' => 2]);
|
||||||
|
|
||||||
|
$this->poinService->deductPoin(
|
||||||
|
$penggunaan->id_user,
|
||||||
|
$penggunaan->jumlah_poin,
|
||||||
|
$penggunaan->id_penggunaan
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
$message = 'Pengajuan berhasil disetujui dan poin telah dipotong.';
|
||||||
|
} else {
|
||||||
|
$penggunaan->update([
|
||||||
|
'id_status' => 3,
|
||||||
|
'alasan_penolakan' => $request->alasan_penolakan
|
||||||
|
]);
|
||||||
|
|
||||||
|
$message = 'Pengajuan berhasil ditolak.';
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->back()->with('success', $message);
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return redirect()->back()->with('error', 'Gagal memproses: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Requests\StorePengumumanRequest;
|
||||||
|
use App\Http\Requests\UpdatePengumumanRequest;
|
||||||
|
use App\Models\Pengumuman;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
|
class PengumumanController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$pengumuman = Pengumuman::with('pembuat')
|
||||||
|
->orderBy('tanggal', 'desc')
|
||||||
|
->paginate(10);
|
||||||
|
|
||||||
|
$title = 'Pengumuman';
|
||||||
|
|
||||||
|
return view('pengumuman.index', compact('pengumuman', 'title'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
$title = 'Buat Pengumuman';
|
||||||
|
return view('pengumuman.create', compact('title'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(StorePengumumanRequest $request)
|
||||||
|
{
|
||||||
|
$data = $request->validated();
|
||||||
|
$data['dibuat_oleh'] = Auth::id();
|
||||||
|
|
||||||
|
Pengumuman::create($data);
|
||||||
|
|
||||||
|
return redirect()->route('pengumuman.index')
|
||||||
|
->with('success', 'Pengumuman berhasil ditambahkan.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit(Pengumuman $pengumuman)
|
||||||
|
{
|
||||||
|
$title = 'Edit Pengumuman';
|
||||||
|
return view('pengumuman.edit', compact('pengumuman', 'title'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(UpdatePengumumanRequest $request, Pengumuman $pengumuman)
|
||||||
|
{
|
||||||
|
$pengumuman->update($request->validated());
|
||||||
|
|
||||||
|
return redirect()->route('pengumuman.index')
|
||||||
|
->with('success', 'Pengumuman berhasil diperbarui.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(Pengumuman $pengumuman)
|
||||||
|
{
|
||||||
|
$pengumuman->delete();
|
||||||
|
|
||||||
|
return redirect()->route('pengumuman.index')
|
||||||
|
->with('success', 'Pengumuman berhasil dihapus.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\Role;
|
||||||
|
use App\Models\Permission;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class PermissionController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$permissions = Permission::all();
|
||||||
|
$roles = Role::with('permissions')->get();
|
||||||
|
return view('permission.index', compact('permissions', 'roles'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'nama_permission' => 'required|unique:permissions,nama_permission',
|
||||||
|
]);
|
||||||
|
|
||||||
|
Permission::create([
|
||||||
|
'nama_permission' => $request->nama_permission,
|
||||||
|
'slug' => \Illuminate\Support\Str::slug($request->nama_permission)
|
||||||
|
]);
|
||||||
|
|
||||||
|
return back()->with('success', 'Permission berhasil dibuat.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sync(Request $request, $id_role)
|
||||||
|
{
|
||||||
|
$role = Role::findOrFail($id_role);
|
||||||
|
$role->permissions()->sync($request->permissions);
|
||||||
|
|
||||||
|
return back()->with('success', 'Hak akses role berhasil diperbarui.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,471 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\Presensi;
|
||||||
|
use App\Models\JadwalKerja;
|
||||||
|
use App\Models\Kantor;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use App\Http\Requests\StorePresensiRequest;
|
||||||
|
use App\Http\Requests\StoreManualPresensiRequest;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
|
class PresensiController extends Controller
|
||||||
|
{
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$tanggal = $request->get('tanggal', Carbon::today()->format('Y-m-d'));
|
||||||
|
$divisiId = $request->get('divisi_id');
|
||||||
|
|
||||||
|
$pendingDates = Presensi::where('id_validasi', 2)
|
||||||
|
->selectRaw('DATE(tanggal) as tgl, COUNT(*) as jumlah')
|
||||||
|
->groupBy('tgl')
|
||||||
|
->orderBy('tgl', 'desc')
|
||||||
|
->get();
|
||||||
|
|
||||||
|
$query = Presensi::with(['user.jabatan', 'user.kantor'])
|
||||||
|
->whereDate('tanggal', $tanggal);
|
||||||
|
|
||||||
|
if ($divisiId) {
|
||||||
|
$query->whereHas('user', function ($q) use ($divisiId) {
|
||||||
|
$q->where('id_divisi', $divisiId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$filterStatus = $request->get('filter_status');
|
||||||
|
if ($filterStatus == 'tepat_waktu') {
|
||||||
|
$query->where('id_status', 1);
|
||||||
|
} elseif ($filterStatus == 'terlambat') {
|
||||||
|
$query->where('id_status', 2);
|
||||||
|
} elseif ($filterStatus == 'pending') {
|
||||||
|
$query->where('id_validasi', 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
$presensi = $query->orderBy('jam_masuk', 'desc')->paginate(15);
|
||||||
|
|
||||||
|
$divisi = \App\Models\Divisi::all();
|
||||||
|
|
||||||
|
$userIds = $presensi->pluck('id_user')->unique();
|
||||||
|
$jadwalCollection = JadwalKerja::with('shift')
|
||||||
|
->whereIn('id_user', $userIds)
|
||||||
|
->where('tanggal', $tanggal)
|
||||||
|
->get()
|
||||||
|
->keyBy('id_user');
|
||||||
|
|
||||||
|
$poinCollection = \App\Models\PenggunaanPoin::with('jenisPengurangan')
|
||||||
|
->whereIn('id_user', $userIds)
|
||||||
|
->where('tanggal_penggunaan', $tanggal)
|
||||||
|
->where('id_status', 2)
|
||||||
|
->get()
|
||||||
|
->keyBy('id_user');
|
||||||
|
|
||||||
|
$presensi->map(function ($item) use ($jadwalCollection, $poinCollection) {
|
||||||
|
$jadwal = $jadwalCollection->get($item->id_user);
|
||||||
|
$poinUsed = $poinCollection->get($item->id_user);
|
||||||
|
|
||||||
|
$jamMasuk = $jadwal && $jadwal->shift ? $jadwal->shift->jam_mulai : '-';
|
||||||
|
$jamPulang = $jadwal && $jadwal->shift ? $jadwal->shift->jam_selesai : '-';
|
||||||
|
|
||||||
|
$item->jam_jadwal_masuk_original = $jamMasuk;
|
||||||
|
$item->jam_jadwal_pulang_original = $jamPulang;
|
||||||
|
$item->is_adjusted = false;
|
||||||
|
$item->adjustment_note = null;
|
||||||
|
|
||||||
|
if ($poinUsed) {
|
||||||
|
$menit = $poinUsed->jumlah_poin * 30;
|
||||||
|
$jenis = $poinUsed->jenisPengurangan->nama_pengurangan ?? '';
|
||||||
|
|
||||||
|
if ($jenis == 'Pulang Cepat' && $jamPulang != '-') {
|
||||||
|
$jamPulang = Carbon::parse($jamPulang)->subMinutes($menit)->format('H:i:s');
|
||||||
|
$item->is_adjusted = true;
|
||||||
|
$item->adjustment_note = "Pulang Cepat -{$menit}m";
|
||||||
|
} elseif ($jenis == 'Datang Terlambat' && $jamMasuk != '-') {
|
||||||
|
$jamMasuk = Carbon::parse($jamMasuk)->addMinutes($menit)->format('H:i:s');
|
||||||
|
$item->is_adjusted = true;
|
||||||
|
$item->adjustment_note = "Datang Telat +{$menit}m";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$item->jam_jadwal_masuk = $jamMasuk;
|
||||||
|
$item->jam_jadwal_pulang = $jamPulang;
|
||||||
|
$item->nama_shift = $jadwal && $jadwal->shift ? $jadwal->shift->nama_shift : 'Non-Shift';
|
||||||
|
|
||||||
|
$item->status_keterlambatan = 'Tepat Waktu';
|
||||||
|
$item->badge_color = 'success';
|
||||||
|
|
||||||
|
if ($item->id_status == 2) {
|
||||||
|
$item->status_keterlambatan = $item->alasan_telat ?? 'Terlambat';
|
||||||
|
$item->badge_color = 'rose';
|
||||||
|
} elseif ($item->id_status == 1) {
|
||||||
|
$item->status_keterlambatan = 'Tepat Waktu';
|
||||||
|
$item->badge_color = 'emerald';
|
||||||
|
}
|
||||||
|
|
||||||
|
$item->validasi_label = $item->id_validasi == 1 ? 'Disetujui' : ($item->id_validasi == 3 ? 'Ditolak' : 'Pending');
|
||||||
|
$item->validasi_color = $item->id_validasi == 1 ? 'emerald' : ($item->id_validasi == 3 ? 'rose' : 'amber');
|
||||||
|
|
||||||
|
$item->jarak_masuk = null;
|
||||||
|
if ($item->user && $item->user->kantor && $item->lat_masuk && $item->lon_masuk) {
|
||||||
|
$item->jarak_masuk = app(self::class)->calculateDistance(
|
||||||
|
$item->lat_masuk,
|
||||||
|
$item->lon_masuk,
|
||||||
|
$item->user->kantor->latitude,
|
||||||
|
$item->user->kantor->longitude
|
||||||
|
);
|
||||||
|
$item->jarak_masuk = round($item->jarak_masuk, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
$item->dalam_radius = false;
|
||||||
|
if ($item->jarak_masuk !== null && $item->user && $item->user->kantor) {
|
||||||
|
$item->dalam_radius = $item->jarak_masuk <= $item->user->kantor->radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $item;
|
||||||
|
});
|
||||||
|
|
||||||
|
return view('presensi.index', compact('presensi', 'tanggal', 'divisi', 'pendingDates'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function approve($id)
|
||||||
|
{
|
||||||
|
$presensi = Presensi::findOrFail($id);
|
||||||
|
$presensi->update(['id_validasi' => 1]);
|
||||||
|
|
||||||
|
return redirect()->back()->with('success', 'Presensi berhasil disetujui.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function reject($id)
|
||||||
|
{
|
||||||
|
$presensi = Presensi::findOrFail($id);
|
||||||
|
$presensi->update(['id_validasi' => 3]);
|
||||||
|
|
||||||
|
return redirect()->back()->with('success', 'Presensi berhasil ditolak.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function bulkAction(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'presensi_ids' => 'required|array',
|
||||||
|
'action' => 'required|in:approve,reject'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$statusValidasi = $request->action == 'approve' ? 1 : 3;
|
||||||
|
|
||||||
|
Presensi::whereIn('id_presensi', $request->presensi_ids)
|
||||||
|
->where('id_validasi', 2)
|
||||||
|
->update(['id_validasi' => $statusValidasi]);
|
||||||
|
|
||||||
|
$statusText = $request->action == 'approve' ? 'disetujui' : 'ditolak';
|
||||||
|
return redirect()->back()->with('success', count($request->presensi_ids) . " pengajuan presensi berhasil {$statusText}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
$pegawai = \App\Models\User::with('divisi')
|
||||||
|
->orderBy('nama_lengkap', 'asc')
|
||||||
|
->get();
|
||||||
|
|
||||||
|
$statuses = \Illuminate\Support\Facades\DB::table('status_presensi')->get();
|
||||||
|
|
||||||
|
return view('presensi.create', compact('pegawai', 'statuses'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function storeManual(StoreManualPresensiRequest $request)
|
||||||
|
{
|
||||||
|
$existing = Presensi::where('id_user', $request->id_user)
|
||||||
|
->where('tanggal', $request->tanggal)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if ($existing) {
|
||||||
|
return redirect()->back()
|
||||||
|
->withInput()
|
||||||
|
->with('error', 'Pegawai bersangkutan sudah memiliki record presensi pada tanggal tersebut. Gunakan fitur Edit (Koreksi) jika ingin mengubah data.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$jamMasuk = $request->jam_masuk ? $request->jam_masuk . ':00' : null;
|
||||||
|
$jamPulang = $request->jam_pulang ? $request->jam_pulang . ':00' : null;
|
||||||
|
|
||||||
|
Presensi::create([
|
||||||
|
'id_user' => $request->id_user,
|
||||||
|
'tanggal' => $request->tanggal,
|
||||||
|
'id_status' => $request->id_status,
|
||||||
|
'jam_masuk' => in_array($request->id_status, [1, 2]) ? $jamMasuk : null,
|
||||||
|
'jam_pulang' => in_array($request->id_status, [1, 2]) ? $jamPulang : null,
|
||||||
|
'alasan_telat' => $request->alasan_telat ?? 'Input Manual oleh Admin',
|
||||||
|
'id_validasi' => 1,
|
||||||
|
'verifikasi_wajah' => 1,
|
||||||
|
'lat_masuk' => null,
|
||||||
|
'lon_masuk' => null,
|
||||||
|
'lat_pulang' => null,
|
||||||
|
'lon_pulang' => null,
|
||||||
|
'keterangan_luar_radius' => 'Input Manual oleh Admin',
|
||||||
|
'foto_wajah_masuk' => null,
|
||||||
|
'foto_wajah_pulang' => null,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return redirect()->route('presensi.index', ['tanggal' => $request->tanggal])
|
||||||
|
->with('success', 'Presensi manual berhasil ditambahkan.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit($id)
|
||||||
|
{
|
||||||
|
$presensi = Presensi::with('user.divisi')->findOrFail($id);
|
||||||
|
$statuses = \Illuminate\Support\Facades\DB::table('status_presensi')->get();
|
||||||
|
|
||||||
|
return view('presensi.edit', compact('presensi', 'statuses'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function updateManual(Request $request, $id)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'id_status' => 'required|exists:status_presensi,id_status',
|
||||||
|
'jam_masuk' => [
|
||||||
|
\Illuminate\Validation\Rule::requiredIf(fn () => in_array($request->id_status, [1, 2])),
|
||||||
|
'nullable',
|
||||||
|
'date_format:H:i'
|
||||||
|
],
|
||||||
|
'jam_pulang' => 'nullable|date_format:H:i',
|
||||||
|
'alasan_telat' => 'required|string|max:255'
|
||||||
|
], [
|
||||||
|
'alasan_telat.required' => 'Catatan koreksi wajib diisi sebagai dokumentasi log.',
|
||||||
|
'jam_masuk.required' => 'Jam masuk wajib diisi untuk kehadiran Hadir/Terlambat.'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$presensi = Presensi::findOrFail($id);
|
||||||
|
|
||||||
|
$jamMasuk = $request->jam_masuk ? $request->jam_masuk . ':00' : null;
|
||||||
|
$jamPulang = $request->jam_pulang ? $request->jam_pulang . ':00' : null;
|
||||||
|
|
||||||
|
$isAdjusted = false;
|
||||||
|
$adjustmentNotes = [];
|
||||||
|
|
||||||
|
if ($presensi->jam_masuk != $jamMasuk && in_array($request->id_status, [1, 2])) {
|
||||||
|
$isAdjusted = true;
|
||||||
|
$adjustmentNotes[] = "Datang dari " . substr($presensi->jam_masuk ?? '-', 0, 5) . " ke " . substr($jamMasuk, 0, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($presensi->jam_pulang != $jamPulang && in_array($request->id_status, [1, 2])) {
|
||||||
|
$isAdjusted = true;
|
||||||
|
$adjustmentNotes[] = "Pulang dari " . substr($presensi->jam_pulang ?? '-', 0, 5) . " ke " . substr($jamPulang, 0, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
$presensi->update([
|
||||||
|
'id_status' => $request->id_status,
|
||||||
|
'jam_masuk' => in_array($request->id_status, [1, 2]) ? $jamMasuk : null,
|
||||||
|
'jam_pulang' => in_array($request->id_status, [1, 2]) ? $jamPulang : null,
|
||||||
|
'alasan_telat' => $request->alasan_telat . ($isAdjusted ? " | [Koreksi Admin: " . implode(', ', $adjustmentNotes) . "]" : ""),
|
||||||
|
'id_validasi' => 1,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return redirect()->route('presensi.index', ['tanggal' => $presensi->tanggal])
|
||||||
|
->with('success', 'Data presensi berhasil dikoreksi.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(StorePresensiRequest $request)
|
||||||
|
{
|
||||||
|
$user = Auth::user();
|
||||||
|
$hariIni = Carbon::today()->toDateString();
|
||||||
|
$jamSekarang = Carbon::now();
|
||||||
|
$status = $request->status;
|
||||||
|
|
||||||
|
if ($status === 'pulang') {
|
||||||
|
return $this->handlePulang($request, $user, $hariIni, $jamSekarang);
|
||||||
|
}
|
||||||
|
|
||||||
|
$jadwal = JadwalKerja::with('shift')
|
||||||
|
->where('id_user', $user->id)
|
||||||
|
->where('tanggal', $hariIni)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if (!$jadwal) {
|
||||||
|
return response()->json([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Anda tidak memiliki jadwal hari ini.'
|
||||||
|
], 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
$cekPresensi = Presensi::where('id_user', $user->id)
|
||||||
|
->where('tanggal', $hariIni)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if ($cekPresensi) {
|
||||||
|
return response()->json([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Anda sudah melakukan absen masuk hari ini.'
|
||||||
|
], 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
$kantor = $user->kantor;
|
||||||
|
if (!$kantor) {
|
||||||
|
return response()->json([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Data kantor belum diatur untuk akun Anda.'
|
||||||
|
], 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
$jarak = $this->calculateDistance(
|
||||||
|
$request->latitude,
|
||||||
|
$request->longitude,
|
||||||
|
$kantor->latitude,
|
||||||
|
$kantor->longitude
|
||||||
|
);
|
||||||
|
|
||||||
|
$radiusKantor = $kantor->radius;
|
||||||
|
$idValidasi = ($jarak <= $radiusKantor) ? 1 : 2;
|
||||||
|
|
||||||
|
$presensiService = new \App\Services\PresensiService();
|
||||||
|
$dynamicSchedule = $presensiService->getDynamicSchedule($user->id, $hariIni);
|
||||||
|
|
||||||
|
$jamMasukEfektif = $dynamicSchedule
|
||||||
|
? $dynamicSchedule['jam_masuk']
|
||||||
|
: $jadwal->shift->jam_mulai;
|
||||||
|
$statusJadwal = $dynamicSchedule['status_jadwal'] ?? 'Normal';
|
||||||
|
|
||||||
|
$jamMasukParsed = Carbon::parse($jamMasukEfektif, 'Asia/Jakarta');
|
||||||
|
$toleransi = 15;
|
||||||
|
$batasToleransi = $jamMasukParsed->copy()->addMinutes($toleransi);
|
||||||
|
|
||||||
|
$idStatus = 1;
|
||||||
|
$alasanTelat = null;
|
||||||
|
|
||||||
|
if ($jamSekarang->greaterThan($batasToleransi)) {
|
||||||
|
$idStatus = 2;
|
||||||
|
$selisihMenit = $jamSekarang->diffInMinutes($jamMasukParsed);
|
||||||
|
$alasanTelat = "Terlambat {$selisihMenit} menit";
|
||||||
|
}
|
||||||
|
|
||||||
|
$fotoFile = $request->file('foto');
|
||||||
|
$imageName = 'masuk_' . $user->id . '_' . time() . '.' . $fotoFile->getClientOriginalExtension();
|
||||||
|
$fotoFile->storeAs('uploads/absensi', $imageName, 'public');
|
||||||
|
|
||||||
|
$verifikasiWajah = 0;
|
||||||
|
$faceMessage = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
$faceService = new \App\Services\FaceRecognitionService();
|
||||||
|
$result = $faceService->verifyFace($user->id, $fotoFile);
|
||||||
|
|
||||||
|
if (isset($result['match']) && $result['match'] === true) {
|
||||||
|
$verifikasiWajah = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$faceMessage = $result['message'] ?? null;
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
$presensi = Presensi::create([
|
||||||
|
'id_user' => $user->id,
|
||||||
|
'tanggal' => $hariIni,
|
||||||
|
'jam_masuk' => $jamSekarang->format('H:i:s'),
|
||||||
|
'lat_masuk' => $request->latitude,
|
||||||
|
'lon_masuk' => $request->longitude,
|
||||||
|
'foto_wajah_masuk' => 'uploads/absensi/' . $imageName,
|
||||||
|
'id_status' => $idStatus,
|
||||||
|
'alasan_telat' => $alasanTelat,
|
||||||
|
'id_validasi' => $idValidasi,
|
||||||
|
'keterangan_luar_radius' => $request->keterangan_luar_radius,
|
||||||
|
'verifikasi_wajah' => $verifikasiWajah,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true,
|
||||||
|
'status' => 'success',
|
||||||
|
'message' => 'Absen masuk berhasil!',
|
||||||
|
'data' => [
|
||||||
|
'jam_masuk' => $jamSekarang->format('H:i'),
|
||||||
|
'status' => ($idStatus == 1) ? 'Tepat Waktu' : 'Terlambat',
|
||||||
|
'jarak' => round($jarak, 2) . ' meter',
|
||||||
|
'validasi_lokasi' => ($idValidasi == 1) ? 'Dalam Radius' : 'Di Luar Radius (Pending)',
|
||||||
|
'verifikasi_wajah' => $verifikasiWajah == 1 ? 'Terverifikasi' : 'Pending',
|
||||||
|
'face_message' => $faceMessage,
|
||||||
|
]
|
||||||
|
], 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handlePulang($request, $user, $hariIni, $jamSekarang)
|
||||||
|
{
|
||||||
|
$presensi = Presensi::where('id_user', $user->id)
|
||||||
|
->whereNull('jam_pulang')
|
||||||
|
->latest()
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if (!$presensi) {
|
||||||
|
return response()->json([
|
||||||
|
'success' => false,
|
||||||
|
'message' => 'Anda belum absen masuk atau sudah absen pulang.'
|
||||||
|
], 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
$fotoFile = $request->file('foto');
|
||||||
|
$imageName = 'pulang_' . $user->id . '_' . time() . '.' . $fotoFile->getClientOriginalExtension();
|
||||||
|
$fotoFile->storeAs('uploads/absensi', $imageName, 'public');
|
||||||
|
|
||||||
|
$verifikasiPulang = 0;
|
||||||
|
try {
|
||||||
|
$faceService = new \App\Services\FaceRecognitionService();
|
||||||
|
$result = $faceService->verifyFace($user->id, $fotoFile);
|
||||||
|
if (isset($result['match']) && $result['match'] === true) {
|
||||||
|
$verifikasiPulang = 1;
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
$presensiService = new \App\Services\PresensiService();
|
||||||
|
$dynamicSchedule = $presensiService->getDynamicSchedule($user->id, $hariIni);
|
||||||
|
|
||||||
|
$jamPulangEfektif = $dynamicSchedule
|
||||||
|
? $dynamicSchedule['jam_pulang']
|
||||||
|
: null;
|
||||||
|
|
||||||
|
$waktuPulangAwal = null;
|
||||||
|
$waktuPulangAkhir = null;
|
||||||
|
|
||||||
|
if ($jamPulangEfektif) {
|
||||||
|
$jamPulangTarget = Carbon::parse($jamPulangEfektif, 'Asia/Jakarta');
|
||||||
|
|
||||||
|
if ($jamSekarang->lessThan($jamPulangTarget)) {
|
||||||
|
$waktuPulangAwal = $jamSekarang->diff($jamPulangTarget)->format('%H:%I:%S');
|
||||||
|
} else if ($jamSekarang->greaterThan($jamPulangTarget)) {
|
||||||
|
$waktuPulangAkhir = $jamSekarang->diff($jamPulangTarget)->format('%H:%I:%S');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$presensi->update([
|
||||||
|
'jam_pulang' => $jamSekarang->format('H:i:s'),
|
||||||
|
'lat_pulang' => $request->latitude,
|
||||||
|
'lon_pulang' => $request->longitude,
|
||||||
|
'foto_wajah_pulang' => 'uploads/absensi/' . $imageName,
|
||||||
|
'waktu_pulang_awal' => $waktuPulangAwal,
|
||||||
|
'waktu_pulang_akhir' => $waktuPulangAkhir,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => true,
|
||||||
|
'status' => 'success',
|
||||||
|
'message' => 'Absen pulang berhasil. Hati-hati di jalan!',
|
||||||
|
'data' => [
|
||||||
|
'jam_pulang' => $jamSekarang->format('H:i'),
|
||||||
|
'verifikasi_wajah' => $verifikasiPulang == 1 ? 'Terverifikasi' : 'Pending',
|
||||||
|
]
|
||||||
|
], 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function calculateDistance($lat1, $lon1, $lat2, $lon2)
|
||||||
|
{
|
||||||
|
$earthRadius = 6371000;
|
||||||
|
|
||||||
|
$dLat = deg2rad($lat2 - $lat1);
|
||||||
|
$dLon = deg2rad($lon2 - $lon1);
|
||||||
|
|
||||||
|
$a = sin($dLat / 2) * sin($dLat / 2) +
|
||||||
|
cos(deg2rad($lat1)) * cos(deg2rad($lat2)) *
|
||||||
|
sin($dLon / 2) * sin($dLon / 2);
|
||||||
|
|
||||||
|
$c = 2 * atan2(sqrt($a), sqrt(1 - $a));
|
||||||
|
|
||||||
|
return $earthRadius * $c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
|
||||||
|
class ProfileController extends Controller
|
||||||
|
{
|
||||||
|
public function edit()
|
||||||
|
{
|
||||||
|
$user = Auth::user();
|
||||||
|
return view('profile.edit', compact('user'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(Request $request)
|
||||||
|
{
|
||||||
|
$user = Auth::user();
|
||||||
|
|
||||||
|
$request->validate([
|
||||||
|
'nama_lengkap' => 'required|string|max:255',
|
||||||
|
'email' => ['required', 'string', 'email', 'max:255', Rule::unique('users')->ignore($user->id)],
|
||||||
|
'foto' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048',
|
||||||
|
'password' => 'nullable|string|min:8|confirmed',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'nama_lengkap' => $request->nama_lengkap,
|
||||||
|
'email' => $request->email,
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($request->filled('password')) {
|
||||||
|
$data['password'] = Hash::make($request->password);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->hasFile('foto')) {
|
||||||
|
if ($user->foto) {
|
||||||
|
Storage::disk('public')->delete($user->foto);
|
||||||
|
}
|
||||||
|
$data['foto'] = $request->file('foto')->store('foto-profil', 'public');
|
||||||
|
}
|
||||||
|
|
||||||
|
$user->update($data);
|
||||||
|
|
||||||
|
return redirect()->route('profile.edit')->with('success', 'Profil berhasil diperbarui.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\Role;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Http\Requests\StoreRoleRequest;
|
||||||
|
use App\Http\Requests\UpdateRoleRequest;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class RoleController extends Controller
|
||||||
|
{
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$query = Role::with(['permissions', 'users']);
|
||||||
|
|
||||||
|
if ($request->filled('search')) {
|
||||||
|
$query->where('nama_role', 'like', '%' . $request->search . '%');
|
||||||
|
}
|
||||||
|
|
||||||
|
$roles = $query->latest('id_role')->paginate(10)->withQueryString();
|
||||||
|
$allPermissions = \App\Models\Permission::orderBy('nama_permission', 'asc')->get();
|
||||||
|
|
||||||
|
return view('role.index', compact('roles', 'allPermissions'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(StoreRoleRequest $request)
|
||||||
|
{
|
||||||
|
$role = Role::create($request->validated());
|
||||||
|
|
||||||
|
if ($request->has('id_permissions')) {
|
||||||
|
$role->permissions()->sync($request->id_permissions);
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->route('role.index')
|
||||||
|
->with('success', 'Role baru berhasil ditambahkan.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(UpdateRoleRequest $request, $id)
|
||||||
|
{
|
||||||
|
$role = Role::findOrFail($id);
|
||||||
|
$role->update($request->validated());
|
||||||
|
|
||||||
|
if ($request->has('id_permissions')) {
|
||||||
|
$role->permissions()->sync($request->id_permissions);
|
||||||
|
} else {
|
||||||
|
$role->permissions()->detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->route('role.index')
|
||||||
|
->with('success', 'Role berhasil diperbarui.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy($id)
|
||||||
|
{
|
||||||
|
$role = Role::findOrFail($id);
|
||||||
|
|
||||||
|
if ($role->users()->exists()) {
|
||||||
|
return redirect()->back()->with('error', 'Role tidak bisa dihapus karena masih digunakan user.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$role->delete();
|
||||||
|
|
||||||
|
return redirect()->route('role.index')
|
||||||
|
->with('success', 'Role berhasil dihapus.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\ShiftKerja;
|
||||||
|
use App\Http\Requests\StoreShiftRequest;
|
||||||
|
use App\Http\Requests\UpdateShiftRequest;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class ShiftController extends Controller
|
||||||
|
{
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$query = ShiftKerja::withCount('jadwalKerja');
|
||||||
|
|
||||||
|
if ($request->filled('search')) {
|
||||||
|
$query->where('nama_shift', 'like', '%' . $request->search . '%');
|
||||||
|
}
|
||||||
|
|
||||||
|
$shifts = $query->latest('id_shift')->paginate(10)->withQueryString();
|
||||||
|
|
||||||
|
return view('shift.index', compact('shifts'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(StoreShiftRequest $request)
|
||||||
|
{
|
||||||
|
ShiftKerja::create($request->validated());
|
||||||
|
|
||||||
|
return redirect()->route('shift.index')
|
||||||
|
->with('success', 'Shift kerja berhasil ditambahkan.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(UpdateShiftRequest $request, $id)
|
||||||
|
{
|
||||||
|
$shift = ShiftKerja::findOrFail($id);
|
||||||
|
$shift->update($request->validated());
|
||||||
|
|
||||||
|
return redirect()->route('shift.index')
|
||||||
|
->with('success', 'Shift kerja berhasil diperbarui.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy($id)
|
||||||
|
{
|
||||||
|
$shift = ShiftKerja::findOrFail($id);
|
||||||
|
|
||||||
|
if ($shift->jadwalKerja()->exists()) {
|
||||||
|
return redirect()->back()
|
||||||
|
->with('error', 'Shift tidak bisa dihapus karena masih digunakan di jadwal.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$shift->delete();
|
||||||
|
|
||||||
|
return redirect()->route('shift.index')
|
||||||
|
->with('success', 'Shift kerja berhasil dihapus.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Requests\StoreSignatureRequest;
|
||||||
|
use App\Models\TandaTangan;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
|
class SignatureController extends Controller
|
||||||
|
{
|
||||||
|
public function show()
|
||||||
|
{
|
||||||
|
$ttd = TandaTangan::where('id_user', Auth::id())->active()->first();
|
||||||
|
return view('signature.show', compact('ttd'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(StoreSignatureRequest $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$base64 = $request->signature_data;
|
||||||
|
|
||||||
|
if (str_contains($base64, ',')) {
|
||||||
|
$base64 = explode(',', $base64)[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
$imageData = base64_decode($base64);
|
||||||
|
if ($imageData === false) {
|
||||||
|
return back()->with('error', 'Data tanda tangan tidak valid.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$fileName = 'uploads/ttd/' . Auth::id() . '_' . time() . '.png';
|
||||||
|
Storage::disk('public')->put($fileName, $imageData);
|
||||||
|
|
||||||
|
TandaTangan::where('id_user', Auth::id())->update(['is_active' => false]);
|
||||||
|
|
||||||
|
TandaTangan::create([
|
||||||
|
'id_user' => Auth::id(),
|
||||||
|
'file_ttd' => $fileName,
|
||||||
|
'is_active' => true,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return back()->with('success', 'Tanda tangan berhasil disimpan.');
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return back()->with('error', 'Gagal menyimpan tanda tangan: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,218 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\SuratIzin;
|
||||||
|
use App\Models\ApprovalSurat;
|
||||||
|
use App\Models\TandaTangan;
|
||||||
|
use App\Models\Presensi;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
|
||||||
|
class SuratIzinController extends Controller
|
||||||
|
{
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$query = SuratIzin::with(['user', 'pengajuanIzin.jenisIzin', 'approvals.approver']);
|
||||||
|
|
||||||
|
if ($request->filled('status')) {
|
||||||
|
$query->where('status_surat', $request->status);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->filled('search')) {
|
||||||
|
$query->whereHas('user', function ($q) use ($request) {
|
||||||
|
$q->where('nama_lengkap', 'like', '%' . $request->search . '%');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$suratList = $query->orderBy('created_at', 'desc')->paginate(15);
|
||||||
|
|
||||||
|
return view('surat-izin.index', compact('suratList'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function show($id)
|
||||||
|
{
|
||||||
|
$surat = SuratIzin::with([
|
||||||
|
'user.jabatan',
|
||||||
|
'user.divisi',
|
||||||
|
'pengajuanIzin.jenisIzin',
|
||||||
|
'tandaTanganPengaju',
|
||||||
|
'approvals.approver.jabatan',
|
||||||
|
'approvals.tandaTanganApprover',
|
||||||
|
])->findOrFail($id);
|
||||||
|
|
||||||
|
$user = Auth::user();
|
||||||
|
$canApprove = false;
|
||||||
|
$tahapApproval = null;
|
||||||
|
|
||||||
|
$isSuperAdmin = $user->roles->contains(function ($role) {
|
||||||
|
return in_array(strtolower($role->nama_role), ['admin', 'super admin', 'super_admin']);
|
||||||
|
});
|
||||||
|
|
||||||
|
if ($surat->status_surat === 'menunggu_manajer' && ($user->roles->contains('nama_role', 'manajer') || $isSuperAdmin)) {
|
||||||
|
$canApprove = true;
|
||||||
|
$tahapApproval = 1;
|
||||||
|
} elseif ($surat->status_surat === 'menunggu_hrd' && ($user->roles->contains('nama_role', 'hrd') || $isSuperAdmin)) {
|
||||||
|
$canApprove = true;
|
||||||
|
$tahapApproval = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ttdApprover = TandaTangan::where('id_user', $user->id)->active()->first();
|
||||||
|
|
||||||
|
return view('surat-izin.show', compact('surat', 'canApprove', 'tahapApproval', 'ttdApprover'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function approve(Request $request, $id)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$surat = SuratIzin::findOrFail($id);
|
||||||
|
$user = Auth::user();
|
||||||
|
|
||||||
|
if (in_array($surat->status_surat, ['disetujui', 'ditolak'])) {
|
||||||
|
return redirect()->back()->with('error', 'Surat ini sudah diproses sebelumnya.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$tahap = null;
|
||||||
|
$isSuperAdmin = $user->roles->contains(function ($role) {
|
||||||
|
return in_array(strtolower($role->nama_role), ['admin', 'super admin', 'super_admin']);
|
||||||
|
});
|
||||||
|
|
||||||
|
if ($surat->status_surat === 'menunggu_manajer' && ($user->roles->contains('nama_role', 'manajer') || $isSuperAdmin)) {
|
||||||
|
$tahap = 1;
|
||||||
|
} elseif ($surat->status_surat === 'menunggu_hrd' && ($user->roles->contains('nama_role', 'hrd') || $isSuperAdmin)) {
|
||||||
|
$tahap = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$tahap) {
|
||||||
|
return redirect()->back()->with('error', 'Anda tidak memiliki akses untuk menyetujui surat ini.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$ttd = TandaTangan::where('id_user', $user->id)->active()->first();
|
||||||
|
if (!$ttd) {
|
||||||
|
return redirect()->back()->with('error', 'Anda belum memiliki tanda tangan digital.');
|
||||||
|
}
|
||||||
|
|
||||||
|
DB::beginTransaction();
|
||||||
|
|
||||||
|
ApprovalSurat::create([
|
||||||
|
'id_surat' => $surat->id_surat,
|
||||||
|
'id_approver' => $user->id,
|
||||||
|
'id_ttd_approver' => $ttd->id_tanda_tangan,
|
||||||
|
'tahap' => $tahap,
|
||||||
|
'status' => 'disetujui',
|
||||||
|
'catatan' => $request->catatan,
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($tahap === 1) {
|
||||||
|
$surat->update(['status_surat' => 'menunggu_hrd']);
|
||||||
|
} elseif ($tahap === 2) {
|
||||||
|
$surat->update(['status_surat' => 'disetujui']);
|
||||||
|
$this->prosesPersetujuanFinal($surat);
|
||||||
|
}
|
||||||
|
|
||||||
|
DB::commit();
|
||||||
|
|
||||||
|
$statusLabel = $tahap === 1 ? 'Menunggu HRD' : 'Disetujui';
|
||||||
|
return redirect()->back()->with('success', "Surat berhasil disetujui. Status: {$statusLabel}");
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
DB::rollBack();
|
||||||
|
return redirect()->back()->with('error', 'Gagal: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function reject(Request $request, $id)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$surat = SuratIzin::findOrFail($id);
|
||||||
|
$user = Auth::user();
|
||||||
|
|
||||||
|
if (in_array($surat->status_surat, ['disetujui', 'ditolak'])) {
|
||||||
|
return redirect()->back()->with('error', 'Surat ini sudah diproses sebelumnya.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$tahap = null;
|
||||||
|
$isSuperAdmin = $user->roles->contains(function ($role) {
|
||||||
|
return in_array(strtolower($role->nama_role), ['admin', 'super admin', 'super_admin']);
|
||||||
|
});
|
||||||
|
|
||||||
|
if ($surat->status_surat === 'menunggu_manajer' && ($user->roles->contains('nama_role', 'manajer') || $isSuperAdmin)) {
|
||||||
|
$tahap = 1;
|
||||||
|
} elseif ($surat->status_surat === 'menunggu_hrd' && ($user->roles->contains('nama_role', 'hrd') || $isSuperAdmin)) {
|
||||||
|
$tahap = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$tahap) {
|
||||||
|
return redirect()->back()->with('error', 'Anda tidak memiliki akses.');
|
||||||
|
}
|
||||||
|
|
||||||
|
DB::beginTransaction();
|
||||||
|
|
||||||
|
ApprovalSurat::create([
|
||||||
|
'id_surat' => $surat->id_surat,
|
||||||
|
'id_approver' => $user->id,
|
||||||
|
'id_ttd_approver' => null,
|
||||||
|
'tahap' => $tahap,
|
||||||
|
'status' => 'ditolak',
|
||||||
|
'catatan' => $request->catatan,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$surat->update(['status_surat' => 'ditolak']);
|
||||||
|
|
||||||
|
if ($surat->pengajuanIzin) {
|
||||||
|
$surat->pengajuanIzin->update(['id_status' => 3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
DB::commit();
|
||||||
|
|
||||||
|
return redirect()->back()->with('success', 'Surat izin berhasil ditolak.');
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
DB::rollBack();
|
||||||
|
return redirect()->back()->with('error', 'Gagal: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function prosesPersetujuanFinal(SuratIzin $surat)
|
||||||
|
{
|
||||||
|
$izin = $surat->pengajuanIzin;
|
||||||
|
if (!$izin)
|
||||||
|
return;
|
||||||
|
|
||||||
|
$izin->load('jenisIzin');
|
||||||
|
$izin->update(['id_status' => 2]);
|
||||||
|
|
||||||
|
$statusPresensiId = 3;
|
||||||
|
if ($izin->id_jenis_izin == 1) {
|
||||||
|
$statusPresensiId = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
$startDate = Carbon::parse($izin->tanggal_mulai, 'Asia/Jakarta');
|
||||||
|
$endDate = Carbon::parse($izin->tanggal_selesai, 'Asia/Jakarta');
|
||||||
|
|
||||||
|
while ($startDate->lte($endDate)) {
|
||||||
|
Presensi::updateOrCreate(
|
||||||
|
[
|
||||||
|
'id_user' => $izin->id_user,
|
||||||
|
'tanggal' => $startDate->format('Y-m-d'),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'id_status' => $statusPresensiId,
|
||||||
|
'jam_masuk' => null,
|
||||||
|
'jam_pulang' => null,
|
||||||
|
'id_validasi' => 1,
|
||||||
|
'alasan_telat' => $izin->jenisIzin->nama_izin . ': ' . $izin->alasan,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
$startDate->addDay();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($izin->id_jenis_izin == 2) {
|
||||||
|
$user = \App\Models\User::find($izin->id_user, ['*']);
|
||||||
|
$jumlahHari = Carbon::parse($izin->tanggal_mulai)->diffInDays(Carbon::parse($izin->tanggal_selesai)) + 1;
|
||||||
|
$user->decrement('sisa_cuti', $jumlahHari);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Models\JadwalKerja;
|
||||||
|
use App\Models\RiwayatTukarShift;
|
||||||
|
use App\Http\Requests\StoreTukarShiftRequest;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
|
||||||
|
class TukarShiftController extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$riwayat = RiwayatTukarShift::with(['user1', 'user2', 'jadwal1.shift', 'jadwal2.shift', 'execAdmin'])
|
||||||
|
->latest()
|
||||||
|
->get();
|
||||||
|
|
||||||
|
return view('tukar-shift.index', compact('riwayat'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
$pegawai = User::with('kantor')->whereDoesntHave('roles', function ($q) {
|
||||||
|
$q->where('nama_role', 'admin')->orWhere('nama_role', 'Admin');
|
||||||
|
})->get();
|
||||||
|
|
||||||
|
$kantor = \App\Models\Kantor::orderBy('nama_kantor', 'asc')->get();
|
||||||
|
|
||||||
|
return view('tukar-shift.create', compact('pegawai', 'kantor'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(StoreTukarShiftRequest $request)
|
||||||
|
{
|
||||||
|
DB::beginTransaction();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$jadwal1 = JadwalKerja::findOrFail($request->id_jadwal_1);
|
||||||
|
$jadwal2 = JadwalKerja::findOrFail($request->id_jadwal_2);
|
||||||
|
|
||||||
|
$tempUser1 = $jadwal1->id_user;
|
||||||
|
$jadwal1->id_user = $jadwal2->id_user;
|
||||||
|
$jadwal2->id_user = $tempUser1;
|
||||||
|
|
||||||
|
$jadwal1->save();
|
||||||
|
$jadwal2->save();
|
||||||
|
|
||||||
|
RiwayatTukarShift::create([
|
||||||
|
'id_user_1' => $request->id_user_1,
|
||||||
|
'id_jadwal_1' => $jadwal1->id_jadwal,
|
||||||
|
'id_user_2' => $request->id_user_2,
|
||||||
|
'id_jadwal_2' => $jadwal2->id_jadwal,
|
||||||
|
'keterangan' => $request->keterangan,
|
||||||
|
'created_by' => Auth::id() ?? 1,
|
||||||
|
]);
|
||||||
|
|
||||||
|
DB::commit();
|
||||||
|
|
||||||
|
return redirect()->route('tukar-shift.index')
|
||||||
|
->with('success', 'Berhasil menukar shift kerja untuk kedua pegawai tersebut.');
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
DB::rollBack();
|
||||||
|
return redirect()->back()
|
||||||
|
->withInput()
|
||||||
|
->with('error', 'Gagal menukar shift: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getJadwalUser(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'id_user' => 'required|exists:users,id'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$startOfMonth = Carbon::now()->startOfMonth()->toDateString();
|
||||||
|
$endOfMonth = Carbon::now()->addMonth()->endOfMonth()->toDateString();
|
||||||
|
|
||||||
|
$jadwal = JadwalKerja::with('shift')
|
||||||
|
->where('id_user', $request->id_user)
|
||||||
|
->whereBetween('tanggal', [$startOfMonth, $endOfMonth])
|
||||||
|
->orderBy('tanggal', 'asc')
|
||||||
|
->get();
|
||||||
|
|
||||||
|
return response()->json($jadwal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
|
class CheckRole
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Menangani permintaan yang masuk.
|
||||||
|
*
|
||||||
|
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
|
||||||
|
*/
|
||||||
|
public function handle(Request $request, Closure $next, ...$roles): Response
|
||||||
|
{
|
||||||
|
if (!Auth::check()) {
|
||||||
|
return redirect('login');
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = Auth::user();
|
||||||
|
|
||||||
|
foreach ($roles as $role) {
|
||||||
|
if ($user->roles()->where('nama_role', $role)->exists()) {
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abort(403, 'Unauthorized action.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class StoreDivisiRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'nama_divisi' => ['required', 'string', 'max:255', 'unique:divisi,nama_divisi'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class StoreHariLiburRequest extends FormRequest
|
||||||
|
{
|
||||||
|
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class StoreJabatanRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'nama_jabatan' => ['required', 'string', 'max:255', 'unique:jabatan,nama_jabatan'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class StoreKantorRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'nama_kantor' => ['required', 'string', 'max:255'],
|
||||||
|
'alamat' => ['nullable', 'string'],
|
||||||
|
|
||||||
|
'latitude' => ['required', 'numeric', 'between:-90,90'],
|
||||||
|
'longitude' => ['required', 'numeric', 'between:-180,180'],
|
||||||
|
'radius' => ['required', 'integer', 'min:10'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class StoreLemburRequest extends FormRequest
|
||||||
|
{
|
||||||
|
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'tanggal_lembur' => 'required|date',
|
||||||
|
'jam_mulai' => 'required|date_format:H:i',
|
||||||
|
'jam_selesai' => 'required|date_format:H:i|after:jam_mulai',
|
||||||
|
'keterangan' => 'nullable|string|max:255',
|
||||||
|
'id_kompensasi' => 'nullable|exists:jenis_kompensasi,id_kompensasi',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get custom attributes for validator errors.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function attributes()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'tanggal_lembur' => 'tanggal lembur',
|
||||||
|
'jam_mulai' => 'jam mulai',
|
||||||
|
'jam_selesai' => 'jam selesai',
|
||||||
|
'id_kompensasi' => 'jenis kompensasi',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get custom messages for validator errors.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function messages(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'jam_selesai.after' => 'Jam selesai harus lebih dari jam mulai.',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
|
||||||
|
class StoreManualPresensiRequest extends FormRequest
|
||||||
|
{
|
||||||
|
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
|
||||||
|
return $this->user()->roles->contains(function ($role) {
|
||||||
|
return in_array(strtolower($role->nama_role), ['admin', 'super admin', 'super_admin']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id_user' => 'required|exists:users,id',
|
||||||
|
'tanggal' => 'required|date',
|
||||||
|
'id_status' => 'required|exists:status_presensi,id_status',
|
||||||
|
'jam_masuk' => [
|
||||||
|
Rule::requiredIf(fn () => in_array($this->id_status, [1, 2])),
|
||||||
|
'nullable',
|
||||||
|
'date_format:H:i'
|
||||||
|
],
|
||||||
|
'jam_pulang' => 'nullable|date_format:H:i',
|
||||||
|
'alasan_telat' => 'nullable|string|max:255'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function messages(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id_user.required' => 'Pegawai harus dipilih.',
|
||||||
|
'id_status.required' => 'Status kehadiran harus dipilih.',
|
||||||
|
'jam_masuk.required' => 'Jam masuk wajib diisi untuk status Hadir/Terlambat.',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class StorePegawaiRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'nik' => ['required', 'numeric', 'unique:users,nik'],
|
||||||
|
'nama_lengkap' => ['required', 'string', 'max:255'],
|
||||||
|
'email' => ['required', 'email', 'unique:users,email'],
|
||||||
|
'no_telp' => ['nullable', 'string', 'max:20'],
|
||||||
|
'alamat' => ['nullable', 'string'],
|
||||||
|
'id_divisi' => ['required', 'exists:divisi,id_divisi'],
|
||||||
|
'id_jabatan' => ['required', 'exists:jabatan,id_jabatan'],
|
||||||
|
'id_kantor' => ['required', 'exists:kantor,id_kantor'],
|
||||||
|
'tgl_bergabung' => ['required', 'date'],
|
||||||
|
'foto' => ['nullable', 'image', 'max:5120'],
|
||||||
|
'sisa_cuti' => ['nullable', 'integer', 'min:0'],
|
||||||
|
'id_role' => ['required', 'exists:roles,id_role'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function messages(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'nik.unique' => 'NIK sudah terdaftar di sistem.',
|
||||||
|
'email.unique' => 'Email ini sudah digunakan oleh pegawai lain.',
|
||||||
|
'id_divisi.exists' => 'Divisi yang dipilih tidak valid.',
|
||||||
|
'id_role.exists' => 'Role yang dipilih tidak valid.',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class StorePengajuanIzinRequest extends FormRequest
|
||||||
|
{
|
||||||
|
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'tanggal_mulai' => 'required|date',
|
||||||
|
'tanggal_selesai' => 'required|date|after_or_equal:tanggal_mulai',
|
||||||
|
'id_jenis_izin' => 'required|exists:jenis_izin,id_jenis_izin',
|
||||||
|
'alasan' => 'required|string|max:150',
|
||||||
|
'bukti_file' => 'nullable|file|mimes:pdf,jpg,jpeg,png|max:2048',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get custom attributes for validator errors.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function attributes()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'tanggal_mulai' => 'tanggal mulai',
|
||||||
|
'tanggal_selesai' => 'tanggal selesai',
|
||||||
|
'id_jenis_izin' => 'jenis izin',
|
||||||
|
'bukti_file' => 'bukti file',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get custom messages for validator errors.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function messages(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'tanggal_selesai.after_or_equal' => 'Tanggal selesai harus sama atau setelah tanggal mulai.',
|
||||||
|
'bukti_file.max' => 'Ukuran file maksimal 2MB.',
|
||||||
|
'bukti_file.mimes' => 'Format file harus PDF, JPG, JPEG, atau PNG.',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class StorePengumumanRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'judul' => 'required|string|max:80',
|
||||||
|
'isi' => 'required|string|max:500',
|
||||||
|
'tanggal' => 'required|date',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function messages(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'judul.required' => 'Judul pengumuman wajib diisi.',
|
||||||
|
'judul.max' => 'Judul maksimal 80 karakter.',
|
||||||
|
'isi.required' => 'Isi pengumuman wajib diisi.',
|
||||||
|
'tanggal.required' => 'Tanggal tayang wajib diisi.',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class StorePresensiRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'latitude' => 'required|numeric',
|
||||||
|
'longitude' => 'required|numeric',
|
||||||
|
'foto' => 'required|file|mimes:jpg,jpeg,png|max:5120',
|
||||||
|
'status' => 'required|in:masuk,pulang',
|
||||||
|
'keterangan_luar_radius' => 'nullable|string|max:500',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function messages(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'foto.required' => 'Foto wajah wajib diambil.',
|
||||||
|
'foto.file' => 'Format foto tidak valid.',
|
||||||
|
'foto.mimes' => 'Foto harus berformat JPG atau PNG.',
|
||||||
|
'foto.max' => 'Ukuran foto maksimal 5MB.',
|
||||||
|
'status.required' => 'Status presensi wajib diisi.',
|
||||||
|
'status.in' => 'Status presensi harus masuk atau pulang.',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class StoreRoleRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'nama_role' => ['required', 'string', 'max:50', 'unique:roles,nama_role'],
|
||||||
|
'id_permissions' => ['nullable', 'array'],
|
||||||
|
'id_permissions.*' => ['exists:permissions,id_permission'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function messages(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'nama_role.required' => 'Nama role wajib diisi.',
|
||||||
|
'nama_role.unique' => 'Nama role ini sudah ada.',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class StoreShiftRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'nama_shift' => ['required', 'string', 'max:50', 'unique:shift_kerja,nama_shift'],
|
||||||
|
'jam_mulai' => ['required', 'date_format:H:i'],
|
||||||
|
'jam_selesai' => ['required', 'date_format:H:i', 'after:jam_mulai'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function messages(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'nama_shift.required' => 'Nama shift wajib diisi.',
|
||||||
|
'nama_shift.unique' => 'Nama shift ini sudah ada.',
|
||||||
|
'jam_mulai.required' => 'Jam mulai wajib diisi.',
|
||||||
|
'jam_selesai.required' => 'Jam selesai wajib diisi.',
|
||||||
|
'jam_selesai.after' => 'Jam selesai harus setelah jam mulai.',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class StoreSignatureRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'signature_data' => 'required|string',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function messages(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'signature_data.required' => 'Data tanda tangan wajib diisi.',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class StoreSuratIzinRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id_izin' => 'required|string|exists:pengajuan_izin,id_izin',
|
||||||
|
'isi_surat' => 'required|string',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function messages(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id_izin.required' => 'ID pengajuan izin wajib diisi.',
|
||||||
|
'id_izin.exists' => 'Pengajuan izin tidak ditemukan.',
|
||||||
|
'isi_surat.required' => 'Isi surat wajib diisi.',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class StoreTukarShiftRequest extends FormRequest
|
||||||
|
{
|
||||||
|
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id_user_1' => 'required|exists:users,id',
|
||||||
|
'id_jadwal_1' => 'required|exists:jadwal_kerja,id_jadwal',
|
||||||
|
'id_user_2' => 'required|exists:users,id|different:id_user_1',
|
||||||
|
'id_jadwal_2' => 'required|exists:jadwal_kerja,id_jadwal|different:id_jadwal_1',
|
||||||
|
'keterangan' => 'nullable|string|max:1000'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function messages(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id_user_1.required' => 'Pegawai pertama harus dipilih.',
|
||||||
|
'id_user_1.exists' => 'Pegawai pertama tidak valid.',
|
||||||
|
'id_jadwal_1.required' => 'Jadwal pegawai pertama harus dipilih.',
|
||||||
|
'id_jadwal_1.exists' => 'Jadwal pegawai pertama tidak valid.',
|
||||||
|
'id_user_2.required' => 'Pegawai kedua harus dipilih.',
|
||||||
|
'id_user_2.exists' => 'Pegawai kedua tidak valid.',
|
||||||
|
'id_user_2.different' => 'Pegawai kedua tidak boleh sama dengan pegawai pertama.',
|
||||||
|
'id_jadwal_2.required' => 'Jadwal pegawai kedua harus dipilih.',
|
||||||
|
'id_jadwal_2.exists' => 'Jadwal pegawai kedua tidak valid.',
|
||||||
|
'id_jadwal_2.different' => 'Jadwal pegawai kedua tidak boleh sama dengan jadwal pegawai pertama.',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class UpdateDivisiRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
|
||||||
|
$id = $this->route('divisi');
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
'nama_divisi' => ['required', 'string', 'max:255', 'unique:divisi,nama_divisi,'.$id.',id_divisi'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class UpdateJabatanRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
$id = $this->route('jabatan');
|
||||||
|
|
||||||
|
return [
|
||||||
|
'nama_jabatan' => ['required', 'string', 'max:255', 'unique:jabatan,nama_jabatan,'.$id.',id_jabatan'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class UpdateKantorRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'nama_kantor' => ['required', 'string', 'max:255'],
|
||||||
|
'alamat' => ['nullable', 'string'],
|
||||||
|
|
||||||
|
'latitude' => ['required', 'numeric', 'between:-90,90'],
|
||||||
|
'longitude' => ['required', 'numeric', 'between:-180,180'],
|
||||||
|
'radius' => ['required', 'integer', 'min:10'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class UpdateLemburRequest extends FormRequest
|
||||||
|
{
|
||||||
|
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'tanggal_lembur' => 'required|date',
|
||||||
|
'jam_mulai' => 'required|date_format:H:i',
|
||||||
|
'jam_selesai' => 'required|date_format:H:i|after:jam_mulai',
|
||||||
|
'keterangan' => 'nullable|string|max:255',
|
||||||
|
'id_kompensasi' => 'nullable|exists:jenis_kompensasi,id_kompensasi',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get custom attributes for validator errors.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function attributes()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'tanggal_lembur' => 'tanggal lembur',
|
||||||
|
'jam_mulai' => 'jam mulai',
|
||||||
|
'jam_selesai' => 'jam selesai',
|
||||||
|
'id_kompensasi' => 'jenis kompensasi',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get custom messages for validator errors.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function messages(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'jam_selesai.after' => 'Jam selesai harus lebih dari jam mulai.',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
|
||||||
|
class UpdatePegawaiRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
$id = $this->route('pegawai');
|
||||||
|
|
||||||
|
return [
|
||||||
|
'nama_lengkap' => ['required', 'string', 'max:255'],
|
||||||
|
'email' => [
|
||||||
|
'required',
|
||||||
|
'email',
|
||||||
|
'unique:users,email,' . $this->route('pegawai')
|
||||||
|
],
|
||||||
|
'no_telp' => ['nullable', 'string', 'max:20'],
|
||||||
|
'alamat' => ['nullable', 'string'],
|
||||||
|
'id_divisi' => ['required', 'exists:divisi,id_divisi'],
|
||||||
|
'id_jabatan' => ['required', 'exists:jabatan,id_jabatan'],
|
||||||
|
'id_kantor' => ['required', 'exists:kantor,id_kantor'],
|
||||||
|
'status_aktif' => ['required', 'in:0,1'],
|
||||||
|
'tgl_bergabung' => ['required', 'date'],
|
||||||
|
'foto' => ['nullable', 'image', 'max:5120'],
|
||||||
|
'sisa_cuti' => ['nullable', 'integer', 'min:0'],
|
||||||
|
'id_role' => ['required', 'exists:roles,id_role'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class UpdatePengajuanIzinRequest extends FormRequest
|
||||||
|
{
|
||||||
|
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'tanggal_mulai' => 'required|date',
|
||||||
|
'tanggal_selesai' => 'required|date|after_or_equal:tanggal_mulai',
|
||||||
|
'id_jenis_izin' => 'required|exists:jenis_izin,id_jenis_izin',
|
||||||
|
'alasan' => 'required|string|max:150',
|
||||||
|
'bukti_file' => 'nullable|file|mimes:pdf,jpg,jpeg,png|max:2048',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get custom attributes for validator errors.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function attributes()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'tanggal_mulai' => 'tanggal mulai',
|
||||||
|
'tanggal_selesai' => 'tanggal selesai',
|
||||||
|
'id_jenis_izin' => 'jenis izin',
|
||||||
|
'bukti_file' => 'bukti file',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get custom messages for validator errors.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function messages(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'tanggal_selesai.after_or_equal' => 'Tanggal selesai harus sama atau setelah tanggal mulai.',
|
||||||
|
'bukti_file.max' => 'Ukuran file maksimal 2MB.',
|
||||||
|
'bukti_file.mimes' => 'Format file harus PDF, JPG, JPEG, atau PNG.',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class UpdatePengumumanRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'judul' => 'required|string|max:80',
|
||||||
|
'isi' => 'required|string|max:500',
|
||||||
|
'tanggal' => 'required|date',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function messages(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'judul.required' => 'Judul pengumuman wajib diisi.',
|
||||||
|
'judul.max' => 'Judul maksimal 80 karakter.',
|
||||||
|
'isi.required' => 'Isi pengumuman wajib diisi.',
|
||||||
|
'tanggal.required' => 'Tanggal tayang wajib diisi.',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class UpdateRoleRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
|
||||||
|
return [
|
||||||
|
'nama_role' => ['required', 'string', 'max:50', 'unique:roles,nama_role,' . $this->route('role') . ',id_role'],
|
||||||
|
'id_permissions' => ['nullable', 'array'],
|
||||||
|
'id_permissions.*' => ['exists:permissions,id_permission'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class UpdateShiftRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'nama_shift' => ['required', 'string', 'max:50', 'unique:shift_kerja,nama_shift,' . $this->route('shift') . ',id_shift'],
|
||||||
|
'jam_mulai' => ['required', 'date_format:H:i'],
|
||||||
|
'jam_selesai' => ['required', 'date_format:H:i', 'after:jam_mulai'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function messages(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'nama_shift.required' => 'Nama shift wajib diisi.',
|
||||||
|
'nama_shift.unique' => 'Nama shift ini sudah ada.',
|
||||||
|
'jam_mulai.required' => 'Jam mulai wajib diisi.',
|
||||||
|
'jam_selesai.required' => 'Jam selesai wajib diisi.',
|
||||||
|
'jam_selesai.after' => 'Jam selesai harus setelah jam mulai.',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property string $id_approval
|
||||||
|
* @property string $id_surat
|
||||||
|
* @property int $id_approver
|
||||||
|
* @property string|null $id_ttd_approver
|
||||||
|
* @property int $tahap 1=Manajer, 2=HRD
|
||||||
|
* @property string $status
|
||||||
|
* @property string|null $catatan
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \App\Models\User $approver
|
||||||
|
* @property-read \App\Models\SuratIzin $suratIzin
|
||||||
|
* @property-read \App\Models\TandaTangan|null $tandaTanganApprover
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ApprovalSurat newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ApprovalSurat newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ApprovalSurat query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ApprovalSurat whereCatatan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ApprovalSurat whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ApprovalSurat whereIdApproval($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ApprovalSurat whereIdApprover($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ApprovalSurat whereIdSurat($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ApprovalSurat whereIdTtdApprover($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ApprovalSurat whereStatus($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ApprovalSurat whereTahap($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ApprovalSurat whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class ApprovalSurat extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'approval_surat';
|
||||||
|
protected $primaryKey = 'id_approval';
|
||||||
|
public $incrementing = false;
|
||||||
|
protected $keyType = 'string';
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'id_surat',
|
||||||
|
'id_approver',
|
||||||
|
'id_ttd_approver',
|
||||||
|
'tahap',
|
||||||
|
'status',
|
||||||
|
'catatan',
|
||||||
|
];
|
||||||
|
|
||||||
|
protected static function booted()
|
||||||
|
{
|
||||||
|
static::creating(function ($model) {
|
||||||
|
if (empty($model->{$model->getKeyName()})) {
|
||||||
|
$prefix = 'APR-' . date('ym') . '-';
|
||||||
|
$model->{$model->getKeyName()} = $prefix . strtoupper(Str::random(5));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function suratIzin()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(SuratIzin::class, 'id_surat', 'id_surat');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function approver()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class, 'id_approver');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function tandaTanganApprover()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(TandaTangan::class, 'id_ttd_approver', 'id_tanda_tangan');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?php
|
||||||
|
namespace App\Models;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id
|
||||||
|
* @property int $id_user
|
||||||
|
* @property string|null $path_model_yml
|
||||||
|
* @property int $is_verified 0:Pending, 1:Approved, 2:Rejected
|
||||||
|
* @property string|null $last_updated
|
||||||
|
* @property string|null $encoding_wajah
|
||||||
|
* @property string $tanggal_latih
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \App\Models\User $user
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DataWajah newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DataWajah newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DataWajah query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DataWajah whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DataWajah whereEncodingWajah($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DataWajah whereId($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DataWajah whereIdUser($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DataWajah whereIsVerified($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DataWajah whereLastUpdated($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DataWajah wherePathModelYml($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DataWajah whereTanggalLatih($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DataWajah whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class DataWajah extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'data_wajah';
|
||||||
|
protected $guarded = [];
|
||||||
|
|
||||||
|
public function user()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class, 'id_user', 'id');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id
|
||||||
|
* @property string $id_penggunaan
|
||||||
|
* @property int $id_poin_sumber
|
||||||
|
* @property int $jumlah_diambil
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \App\Models\PenggunaanPoin $penggunaan
|
||||||
|
* @property-read \App\Models\PoinLembur $poinSumber
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DetailPenggunaanPoin newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DetailPenggunaanPoin newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DetailPenggunaanPoin query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DetailPenggunaanPoin whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DetailPenggunaanPoin whereId($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DetailPenggunaanPoin whereIdPenggunaan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DetailPenggunaanPoin whereIdPoinSumber($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DetailPenggunaanPoin whereJumlahDiambil($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|DetailPenggunaanPoin whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class DetailPenggunaanPoin extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $table = 'detail_penggunaan_poin';
|
||||||
|
protected $primaryKey = 'id';
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'id_penggunaan',
|
||||||
|
'id_poin_sumber',
|
||||||
|
'jumlah_diambil'
|
||||||
|
];
|
||||||
|
|
||||||
|
public function penggunaan()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(PenggunaanPoin::class, 'id_penggunaan', 'id_penggunaan');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function poinSumber()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(PoinLembur::class, 'id_poin_sumber', 'id_poin');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id_divisi
|
||||||
|
* @property string $nama_divisi
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Divisi newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Divisi newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Divisi query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Divisi whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Divisi whereIdDivisi($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Divisi whereNamaDivisi($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Divisi whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class Divisi extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $table = 'divisi';
|
||||||
|
protected $primaryKey = 'id_divisi';
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'nama_divisi'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class HariLibur extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $table = 'hari_libur';
|
||||||
|
protected $primaryKey = 'id';
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'tanggal',
|
||||||
|
'keterangan',
|
||||||
|
'id_kantor',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function kantor()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Kantor::class, 'id_kantor');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id_jabatan
|
||||||
|
* @property string $nama_jabatan
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Jabatan newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Jabatan newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Jabatan query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Jabatan whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Jabatan whereIdJabatan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Jabatan whereNamaJabatan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Jabatan whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class Jabatan extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $table = 'jabatan';
|
||||||
|
protected $primaryKey = 'id_jabatan';
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'nama_jabatan'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id_jadwal
|
||||||
|
* @property int|null $id_user
|
||||||
|
* @property string|null $tanggal
|
||||||
|
* @property int|null $id_shift
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \App\Models\PenggunaanPoin|null $penggunaanPoin
|
||||||
|
* @property-read \App\Models\ShiftKerja|null $shift
|
||||||
|
* @property-read \App\Models\User|null $user
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JadwalKerja newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JadwalKerja newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JadwalKerja query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JadwalKerja whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JadwalKerja whereIdJadwal($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JadwalKerja whereIdShift($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JadwalKerja whereIdUser($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JadwalKerja whereTanggal($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JadwalKerja whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class JadwalKerja extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $table = 'jadwal_kerja';
|
||||||
|
protected $primaryKey = 'id_jadwal';
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'id_user',
|
||||||
|
'id_shift',
|
||||||
|
'tanggal',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function user()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class, 'id_user');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function shift()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(ShiftKerja::class, 'id_shift');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function penggunaanPoin()
|
||||||
|
{
|
||||||
|
return $this->hasOne(PenggunaanPoin::class, 'id_user', 'id_user')
|
||||||
|
->whereColumn('tanggal_penggunaan', 'tanggal')
|
||||||
|
->where('id_status', 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id_jenis_izin
|
||||||
|
* @property string $nama_izin
|
||||||
|
* @property string|null $created_at
|
||||||
|
* @property string|null $updated_at
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisIzin newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisIzin newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisIzin query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisIzin whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisIzin whereIdJenisIzin($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisIzin whereNamaIzin($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisIzin whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class JenisIzin extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'jenis_izin';
|
||||||
|
protected $primaryKey = 'id_jenis_izin';
|
||||||
|
public $timestamps = false;
|
||||||
|
|
||||||
|
protected $fillable = ['id_jenis_izin', 'nama_izin'];
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id_kompensasi
|
||||||
|
* @property string $nama_kompensasi
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisKompensasi newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisKompensasi newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisKompensasi query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisKompensasi whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisKompensasi whereIdKompensasi($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisKompensasi whereNamaKompensasi($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisKompensasi whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class JenisKompensasi extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'jenis_kompensasi';
|
||||||
|
protected $primaryKey = 'id_kompensasi';
|
||||||
|
|
||||||
|
const UANG = 1;
|
||||||
|
const POIN = 2;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id_pengurangan
|
||||||
|
* @property string $nama_pengurangan
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\PenggunaanPoin> $penggunaanPoin
|
||||||
|
* @property-read int|null $penggunaan_poin_count
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisPengurangan newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisPengurangan newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisPengurangan query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisPengurangan whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisPengurangan whereIdPengurangan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisPengurangan whereNamaPengurangan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|JenisPengurangan whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class JenisPengurangan extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $table = 'jenis_pengurangan';
|
||||||
|
protected $primaryKey = 'id_pengurangan';
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'nama_pengurangan'
|
||||||
|
];
|
||||||
|
|
||||||
|
public function penggunaanPoin()
|
||||||
|
{
|
||||||
|
return $this->hasMany(PenggunaanPoin::class, 'id_pengurangan');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id_kantor
|
||||||
|
* @property string $nama_kantor
|
||||||
|
* @property string|null $alamat
|
||||||
|
* @property numeric|null $latitude
|
||||||
|
* @property numeric|null $longitude
|
||||||
|
* @property int $radius
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\User> $users
|
||||||
|
* @property-read int|null $users_count
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Kantor newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Kantor newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Kantor query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Kantor whereAlamat($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Kantor whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Kantor whereIdKantor($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Kantor whereLatitude($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Kantor whereLongitude($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Kantor whereNamaKantor($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Kantor whereRadius($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Kantor whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class Kantor extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $table = 'kantor';
|
||||||
|
protected $primaryKey = 'id_kantor';
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'nama_kantor',
|
||||||
|
'tipe',
|
||||||
|
'alamat',
|
||||||
|
'latitude',
|
||||||
|
'longitude',
|
||||||
|
'radius'
|
||||||
|
];
|
||||||
|
|
||||||
|
public function users()
|
||||||
|
{
|
||||||
|
|
||||||
|
return $this->hasMany(User::class, 'id_kantor');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property string $id_lembur
|
||||||
|
* @property int|null $id_user
|
||||||
|
* @property \Illuminate\Support\Carbon $tanggal_lembur
|
||||||
|
* @property string $jam_mulai
|
||||||
|
* @property string $jam_selesai
|
||||||
|
* @property int|null $durasi_menit
|
||||||
|
* @property string|null $keterangan
|
||||||
|
* @property int|null $jumlah_poin
|
||||||
|
* @property int|null $id_kompensasi
|
||||||
|
* @property int $id_status
|
||||||
|
* @property string|null $alasan_penolakan
|
||||||
|
* @property \Illuminate\Support\Carbon $tanggal_diajukan
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \App\Models\JenisKompensasi|null $kompensasi
|
||||||
|
* @property-read \App\Models\StatusPengajuan $status
|
||||||
|
* @property-read \App\Models\User|null $user
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur whereAlasanPenolakan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur whereDurasiMenit($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur whereIdKompensasi($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur whereIdLembur($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur whereIdStatus($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur whereIdUser($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur whereJamMulai($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur whereJamSelesai($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur whereJumlahPoin($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur whereKeterangan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur whereTanggalDiajukan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur whereTanggalLembur($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Lembur whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class Lembur extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $table = 'lembur';
|
||||||
|
protected $primaryKey = 'id_lembur';
|
||||||
|
public $incrementing = false;
|
||||||
|
protected $keyType = 'string';
|
||||||
|
|
||||||
|
protected static function booted()
|
||||||
|
{
|
||||||
|
static::creating(function ($model) {
|
||||||
|
if (empty($model->{$model->getKeyName()})) {
|
||||||
|
$prefix = 'LMB-' . date('ym') . '-';
|
||||||
|
$model->{$model->getKeyName()} = $prefix . strtoupper(\Illuminate\Support\Str::random(5));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'id_user',
|
||||||
|
'tanggal_lembur',
|
||||||
|
'jam_mulai',
|
||||||
|
'jam_selesai',
|
||||||
|
'durasi_menit',
|
||||||
|
'keterangan',
|
||||||
|
'jumlah_poin',
|
||||||
|
'id_kompensasi',
|
||||||
|
'id_status',
|
||||||
|
'alasan_penolakan',
|
||||||
|
'tanggal_diajukan'
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
'tanggal_lembur' => 'date',
|
||||||
|
'tanggal_diajukan' => 'datetime',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function user()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class, 'id_user');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function kompensasi()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(JenisKompensasi::class, 'id_kompensasi');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function status()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(StatusPengajuan::class, 'id_status');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,90 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property string $id_izin
|
||||||
|
* @property int|null $id_user
|
||||||
|
* @property string $tanggal_mulai
|
||||||
|
* @property string $tanggal_selesai
|
||||||
|
* @property int|null $id_jenis_izin
|
||||||
|
* @property string|null $alasan
|
||||||
|
* @property string|null $bukti_file
|
||||||
|
* @property int $id_status
|
||||||
|
* @property string|null $alasan_penolakan
|
||||||
|
* @property string $tanggal_diajukan
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \App\Models\JenisIzin|null $jenisIzin
|
||||||
|
* @property-read \App\Models\StatusPengajuan $statusPengajuan
|
||||||
|
* @property-read \App\Models\User|null $user
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PengajuanIzin newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PengajuanIzin newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PengajuanIzin query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PengajuanIzin whereAlasan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PengajuanIzin whereAlasanPenolakan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PengajuanIzin whereBuktiFile($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PengajuanIzin whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PengajuanIzin whereIdIzin($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PengajuanIzin whereIdJenisIzin($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PengajuanIzin whereIdStatus($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PengajuanIzin whereIdUser($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PengajuanIzin whereTanggalDiajukan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PengajuanIzin whereTanggalMulai($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PengajuanIzin whereTanggalSelesai($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PengajuanIzin whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class PengajuanIzin extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $table = 'pengajuan_izin';
|
||||||
|
protected $primaryKey = 'id_izin';
|
||||||
|
public $incrementing = false;
|
||||||
|
protected $keyType = 'string';
|
||||||
|
|
||||||
|
protected static function booted()
|
||||||
|
{
|
||||||
|
static::creating(function ($model) {
|
||||||
|
if (empty($model->{$model->getKeyName()})) {
|
||||||
|
$prefix = 'IZN-' . date('ym') . '-';
|
||||||
|
$model->{$model->getKeyName()} = $prefix . strtoupper(\Illuminate\Support\Str::random(5));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'id_user',
|
||||||
|
'id_jenis_izin',
|
||||||
|
'id_status',
|
||||||
|
'tanggal_mulai',
|
||||||
|
'tanggal_selesai',
|
||||||
|
'alasan',
|
||||||
|
'bukti_file',
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
public function user()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class, 'id_user');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function jenisIzin()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(JenisIzin::class, 'id_jenis_izin', 'id_jenis_izin');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function statusPengajuan()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(StatusPengajuan::class, 'id_status', 'id_status');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function suratIzin()
|
||||||
|
{
|
||||||
|
return $this->hasOne(SuratIzin::class, 'id_izin', 'id_izin');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property string $id_penggunaan
|
||||||
|
* @property int|null $id_user
|
||||||
|
* @property \Illuminate\Support\Carbon $tanggal_penggunaan
|
||||||
|
* @property int|null $jumlah_poin
|
||||||
|
* @property string|null $jam_masuk_custom
|
||||||
|
* @property string|null $jam_pulang_custom
|
||||||
|
* @property int|null $id_pengurangan
|
||||||
|
* @property int $id_status
|
||||||
|
* @property string|null $alasan_penolakan
|
||||||
|
* @property \Illuminate\Support\Carbon $tanggal_diajukan
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \App\Models\JenisPengurangan|null $jenisPengurangan
|
||||||
|
* @property-read \App\Models\StatusPengajuan $status
|
||||||
|
* @property-read \App\Models\User|null $user
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PenggunaanPoin newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PenggunaanPoin newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PenggunaanPoin query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PenggunaanPoin whereAlasanPenolakan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PenggunaanPoin whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PenggunaanPoin whereIdPenggunaan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PenggunaanPoin whereIdPengurangan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PenggunaanPoin whereIdStatus($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PenggunaanPoin whereIdUser($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PenggunaanPoin whereJamMasukCustom($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PenggunaanPoin whereJamPulangCustom($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PenggunaanPoin whereJumlahPoin($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PenggunaanPoin whereTanggalDiajukan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PenggunaanPoin whereTanggalPenggunaan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PenggunaanPoin whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class PenggunaanPoin extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $table = 'penggunaan_poin';
|
||||||
|
protected $primaryKey = 'id_penggunaan';
|
||||||
|
public $incrementing = false;
|
||||||
|
protected $keyType = 'string';
|
||||||
|
|
||||||
|
protected static function booted()
|
||||||
|
{
|
||||||
|
static::creating(function ($model) {
|
||||||
|
if (empty($model->{$model->getKeyName()})) {
|
||||||
|
$prefix = 'PNP-' . date('ym') . '-';
|
||||||
|
$model->{$model->getKeyName()} = $prefix . strtoupper(\Illuminate\Support\Str::random(5));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'id_user',
|
||||||
|
'tanggal_penggunaan',
|
||||||
|
'jumlah_poin',
|
||||||
|
'id_pengurangan',
|
||||||
|
'jam_masuk_custom',
|
||||||
|
'jam_pulang_custom',
|
||||||
|
'id_status',
|
||||||
|
'alasan_penolakan',
|
||||||
|
'tanggal_diajukan'
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
'tanggal_penggunaan' => 'date',
|
||||||
|
'tanggal_diajukan' => 'datetime',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function user()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class, 'id_user');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function jenisPengurangan()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(JenisPengurangan::class, 'id_pengurangan');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function status()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(StatusPengajuan::class, 'id_status', 'id_status');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id_pengumuman
|
||||||
|
* @property string|null $judul
|
||||||
|
* @property string|null $isi
|
||||||
|
* @property \Illuminate\Support\Carbon|null $tanggal
|
||||||
|
* @property int|null $dibuat_oleh
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \App\Models\User|null $pembuat
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Pengumuman newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Pengumuman newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Pengumuman query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Pengumuman whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Pengumuman whereDibuatOleh($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Pengumuman whereIdPengumuman($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Pengumuman whereIsi($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Pengumuman whereJudul($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Pengumuman whereTanggal($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Pengumuman whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class Pengumuman extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $table = 'pengumuman';
|
||||||
|
protected $primaryKey = 'id_pengumuman';
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'judul',
|
||||||
|
'isi',
|
||||||
|
'tanggal',
|
||||||
|
'dibuat_oleh'
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
'tanggal' => 'date',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function pembuat()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class, 'dibuat_oleh', 'id');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id_permission
|
||||||
|
* @property string $nama_permission
|
||||||
|
* @property string $slug
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Role> $roles
|
||||||
|
* @property-read int|null $roles_count
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Permission newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Permission newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Permission query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Permission whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Permission whereIdPermission($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Permission whereNamaPermission($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Permission whereSlug($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Permission whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class Permission extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'permissions';
|
||||||
|
protected $primaryKey = 'id_permission';
|
||||||
|
protected $fillable = ['nama_permission', 'slug'];
|
||||||
|
|
||||||
|
public function roles(): BelongsToMany
|
||||||
|
{
|
||||||
|
return $this->belongsToMany(Role::class, 'detail_role_permissions', 'id_permission', 'id_role');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property-read \App\Models\User|null $user
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Poin newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Poin newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Poin query()
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class Poin extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'poin';
|
||||||
|
protected $primaryKey = 'id_poin';
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'id_user',
|
||||||
|
'jumlah_poin',
|
||||||
|
'sumber',
|
||||||
|
'tgl_kadaluarsa',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function user()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class, 'id_user', 'id');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id_poin
|
||||||
|
* @property int|null $id_user
|
||||||
|
* @property int|null $jumlah_poin
|
||||||
|
* @property int|null $sisa_poin
|
||||||
|
* @property string|null $id_lembur
|
||||||
|
* @property string|null $keterangan
|
||||||
|
* @property \Illuminate\Support\Carbon $tanggal
|
||||||
|
* @property \Illuminate\Support\Carbon|null $expired_at
|
||||||
|
* @property bool|null $is_fully_used
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \App\Models\Lembur|null $lembur
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PoinLembur newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PoinLembur newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PoinLembur query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PoinLembur whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PoinLembur whereExpiredAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PoinLembur whereIdLembur($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PoinLembur whereIdPoin($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PoinLembur whereIdUser($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PoinLembur whereIsFullyUsed($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PoinLembur whereJumlahPoin($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PoinLembur whereKeterangan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PoinLembur whereSisaPoin($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PoinLembur whereTanggal($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|PoinLembur whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class PoinLembur extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $table = 'poin_lembur';
|
||||||
|
protected $primaryKey = 'id_poin';
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'id_user',
|
||||||
|
'id_lembur',
|
||||||
|
'jumlah_poin',
|
||||||
|
'tanggal',
|
||||||
|
'keterangan',
|
||||||
|
'sisa_poin',
|
||||||
|
'expired_at',
|
||||||
|
'is_fully_used'
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
'tanggal' => 'datetime',
|
||||||
|
'expired_at' => 'date',
|
||||||
|
'is_fully_used' => 'boolean',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function lembur()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Lembur::class, 'id_lembur');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
<?php
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id_presensi
|
||||||
|
* @property int|null $id_user
|
||||||
|
* @property string $tanggal
|
||||||
|
* @property string|null $jam_masuk
|
||||||
|
* @property string|null $jam_pulang
|
||||||
|
* @property numeric|null $lat_masuk
|
||||||
|
* @property numeric|null $lon_masuk
|
||||||
|
* @property numeric|null $lat_pulang
|
||||||
|
* @property numeric|null $lon_pulang
|
||||||
|
* @property string|null $foto_wajah_masuk
|
||||||
|
* @property string|null $foto_wajah_pulang
|
||||||
|
* @property int|null $id_status
|
||||||
|
* @property string|null $alasan_telat
|
||||||
|
* @property string|null $keterangan_pulang
|
||||||
|
* @property string|null $waktu_terlambat
|
||||||
|
* @property string|null $waktu_masuk_awal
|
||||||
|
* @property string|null $waktu_pulang_awal
|
||||||
|
* @property string|null $waktu_pulang_akhir
|
||||||
|
* @property int $verifikasi_wajah
|
||||||
|
* @property int $id_validasi
|
||||||
|
* @property string|null $keterangan_luar_radius
|
||||||
|
* @property string|null $alasan_penolakan
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property string|null $deleted_at
|
||||||
|
* @property-read \App\Models\User|null $user
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereAlasanPenolakan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereAlasanTelat($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereDeletedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereFotoWajahMasuk($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereFotoWajahPulang($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereIdPresensi($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereIdStatus($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereIdUser($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereIdValidasi($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereJamMasuk($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereJamPulang($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereKeteranganLuarRadius($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereKeteranganPulang($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereLatMasuk($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereLatPulang($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereLonMasuk($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereLonPulang($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereTanggal($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereUpdatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereVerifikasiWajah($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereWaktuMasukAwal($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereWaktuPulangAkhir($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereWaktuPulangAwal($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Presensi whereWaktuTerlambat($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class Presensi extends Model
|
||||||
|
{
|
||||||
|
|
||||||
|
protected $table = 'presensi';
|
||||||
|
protected $primaryKey = 'id_presensi';
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'id_user',
|
||||||
|
'tanggal',
|
||||||
|
'jam_masuk',
|
||||||
|
'jam_pulang',
|
||||||
|
'lat_masuk',
|
||||||
|
'lon_masuk',
|
||||||
|
'lat_pulang',
|
||||||
|
'lon_pulang',
|
||||||
|
'foto_wajah_masuk',
|
||||||
|
'foto_wajah_pulang',
|
||||||
|
'id_status',
|
||||||
|
'alasan_telat',
|
||||||
|
'verifikasi_wajah',
|
||||||
|
'id_validasi',
|
||||||
|
'alasan_penolakan',
|
||||||
|
'keterangan_luar_radius',
|
||||||
|
'keterangan_pulang',
|
||||||
|
'waktu_terlambat',
|
||||||
|
'waktu_masuk_awal',
|
||||||
|
'waktu_pulang_awal',
|
||||||
|
'waktu_pulang_akhir'
|
||||||
|
];
|
||||||
|
|
||||||
|
public function user()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class, 'id_user');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id_riwayat
|
||||||
|
* @property int $id_user_1
|
||||||
|
* @property int $id_jadwal_1
|
||||||
|
* @property int $id_user_2
|
||||||
|
* @property int $id_jadwal_2
|
||||||
|
* @property string|null $keterangan
|
||||||
|
* @property int $created_by
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \App\Models\User $execAdmin
|
||||||
|
* @property-read \App\Models\JadwalKerja $jadwal1
|
||||||
|
* @property-read \App\Models\JadwalKerja $jadwal2
|
||||||
|
* @property-read \App\Models\User $user1
|
||||||
|
* @property-read \App\Models\User $user2
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|RiwayatTukarShift newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|RiwayatTukarShift newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|RiwayatTukarShift query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|RiwayatTukarShift whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|RiwayatTukarShift whereCreatedBy($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|RiwayatTukarShift whereIdJadwal1($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|RiwayatTukarShift whereIdJadwal2($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|RiwayatTukarShift whereIdRiwayat($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|RiwayatTukarShift whereIdUser1($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|RiwayatTukarShift whereIdUser2($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|RiwayatTukarShift whereKeterangan($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|RiwayatTukarShift whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class RiwayatTukarShift extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'riwayat_tukar_shift';
|
||||||
|
protected $primaryKey = 'id_riwayat';
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'id_user_1',
|
||||||
|
'id_jadwal_1',
|
||||||
|
'id_user_2',
|
||||||
|
'id_jadwal_2',
|
||||||
|
'keterangan',
|
||||||
|
'created_by',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function user1()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class, 'id_user_1', 'id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function jadwal1()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(JadwalKerja::class, 'id_jadwal_1', 'id_jadwal');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function user2()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class, 'id_user_2', 'id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function jadwal2()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(JadwalKerja::class, 'id_jadwal_2', 'id_jadwal');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execAdmin()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class, 'created_by', 'id');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id_role
|
||||||
|
* @property string $nama_role
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\Permission> $permissions
|
||||||
|
* @property-read int|null $permissions_count
|
||||||
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\User> $users
|
||||||
|
* @property-read int|null $users_count
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Role newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Role newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Role query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Role whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Role whereIdRole($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Role whereNamaRole($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|Role whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class Role extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'roles';
|
||||||
|
protected $primaryKey = 'id_role';
|
||||||
|
protected $fillable = ['nama_role'];
|
||||||
|
|
||||||
|
public function users(): BelongsToMany
|
||||||
|
{
|
||||||
|
return $this->belongsToMany(User::class, 'detail_user_roles', 'id_role', 'id_user');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function permissions(): BelongsToMany
|
||||||
|
{
|
||||||
|
return $this->belongsToMany(Permission::class, 'detail_role_permissions', 'id_role', 'id_permission');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id_shift
|
||||||
|
* @property string|null $nama_shift
|
||||||
|
* @property string|null $jam_mulai
|
||||||
|
* @property string|null $jam_selesai
|
||||||
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
|
* @property-read \Illuminate\Database\Eloquent\Collection<int, \App\Models\JadwalKerja> $jadwalKerja
|
||||||
|
* @property-read int|null $jadwal_kerja_count
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ShiftKerja newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ShiftKerja newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ShiftKerja query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ShiftKerja whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ShiftKerja whereIdShift($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ShiftKerja whereJamMulai($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ShiftKerja whereJamSelesai($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ShiftKerja whereNamaShift($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|ShiftKerja whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class ShiftKerja extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $table = 'shift_kerja';
|
||||||
|
protected $primaryKey = 'id_shift';
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'nama_shift',
|
||||||
|
'jam_mulai',
|
||||||
|
'jam_selesai',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function jadwalKerja(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(JadwalKerja::class, 'id_shift', 'id_shift');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id_status
|
||||||
|
* @property string $nama_status
|
||||||
|
* @property string|null $created_at
|
||||||
|
* @property string|null $updated_at
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|StatusPengajuan newModelQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|StatusPengajuan newQuery()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|StatusPengajuan query()
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|StatusPengajuan whereCreatedAt($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|StatusPengajuan whereIdStatus($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|StatusPengajuan whereNamaStatus($value)
|
||||||
|
* @method static \Illuminate\Database\Eloquent\Builder<static>|StatusPengajuan whereUpdatedAt($value)
|
||||||
|
* @mixin \Eloquent
|
||||||
|
*/
|
||||||
|
class StatusPengajuan extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'status_pengajuan';
|
||||||
|
protected $primaryKey = 'id_status';
|
||||||
|
public $timestamps = false;
|
||||||
|
|
||||||
|
protected $fillable = ['id_status', 'nama_status'];
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue