first commit
This commit is contained in:
commit
f01cfe7152
|
|
@ -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,64 @@
|
|||
APP_NAME=Laravel
|
||||
APP_ENV=local
|
||||
APP_KEY=base64:JCHuHMTGBSdSPEnmKhtW4iMbEy34yaBrHK8T9pX6r7k=
|
||||
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=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=pencatatanobat2
|
||||
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=smtp
|
||||
MAIL_HOST=smtp-relay.brevo.com
|
||||
MAIL_PORT=587
|
||||
MAIL_USERNAME=aa5d12001@smtp-brevo.com
|
||||
MAIL_PASSWORD=xsmtpsib-dfa58e574c1f22cc4275cfbc4be470e6a1ed321485af02d908fa26d7708ba3ad-FmgHA9sAQoojTdH9
|
||||
MAIL_FROM_ADDRESS="mbakgopie@gmail.com"
|
||||
MAIL_FROM_NAME="MedData Puskesmas"
|
||||
|
||||
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,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,23 @@
|
|||
*.log
|
||||
.DS_Store
|
||||
.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
|
||||
|
|
@ -0,0 +1,213 @@
|
|||
# MedData — Sistem Pendataan Obat Puskesmas
|
||||
|
||||
Aplikasi web untuk pencatatan, pengelolaan, dan monitoring obat di Puskesmas. Dilengkapi dengan manajemen resep, laporan, monitoring kadaluarsa, dan dashboard interaktif.
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
---
|
||||
|
||||
## 📋 Fitur Utama
|
||||
|
||||
### 🏠 Dashboard
|
||||
- Statistik: total jenis obat, obat masuk/keluar bulan ini, obat mendekati kadaluarsa
|
||||
- Grafik tren harian obat masuk vs keluar (filter per bulan/tahun)
|
||||
- Pie chart distribusi obat masuk (top 5)
|
||||
- Notifikasi real-time obat mendekati kadaluarsa
|
||||
|
||||
### 📥 Obat Masuk
|
||||
- CRUD lengkap data penerimaan obat
|
||||
- Field: nama obat, kode batch, kategori, satuan, supplier, stok, harga, tanggal penerimaan & kadaluarsa
|
||||
- Search dan filter status stok (tersedia/habis)
|
||||
- Chart distribusi obat per bulan
|
||||
|
||||
### 📤 Obat Keluar
|
||||
- Pencatatan pengeluaran obat terhubung ke data obat masuk
|
||||
- Pemotongan stok otomatis saat pengeluaran, pemulihan saat dihapus
|
||||
- Validasi stok tidak boleh melebihi yang tersedia
|
||||
- Filter berdasarkan status, tujuan pemakaian, barcode
|
||||
|
||||
### 📝 Resep
|
||||
- Pembuatan resep oleh Dokter (multi-item per resep)
|
||||
- Stok obat otomatis berkurang saat resep dibuat
|
||||
- Alur status: `proses` → `selesai` / `dibatalkan` (dikonfirmasi Apoteker)
|
||||
- Update status resep sekaligus memperbarui status Obat Keluar terkait
|
||||
- No. resep otomatis: `RSP-YYYYMMDD-NNNN`
|
||||
|
||||
### ⏰ Monitoring Kadaluarsa
|
||||
- Tampilan obat yang sudah/mendekati kadaluarsa (≤ 60 hari)
|
||||
- Filter: Semua, Sudah Kadaluarsa, Awas (≤ 30 hari), Waspada (≤ 60 hari)
|
||||
- Badge status berwarna (Aman / Waspada / Awas)
|
||||
|
||||
### 📊 Laporan
|
||||
- Laporan obat masuk dan keluar
|
||||
- Filter berdasarkan jenis dan rentang tanggal
|
||||
- Export ke **PDF** (DomPDF) dan **Excel** (Maatwebsite)
|
||||
|
||||
### 🗂️ Master Data
|
||||
- Manajemen Kategori Obat
|
||||
- Manajemen Satuan Obat
|
||||
|
||||
### 👤 Profil
|
||||
- Update profil: nama, email, NIP, gender, nomor telepon, divisi, jabatan, alamat
|
||||
- Ubah password
|
||||
- Upload foto profil
|
||||
|
||||
---
|
||||
|
||||
## 🔐 Sistem Peran (Role)
|
||||
|
||||
| Role | Akses |
|
||||
|------|-------|
|
||||
| **Dokter** | Buat/edit/hapus Resep |
|
||||
| **Apoteker** | Obat Masuk, Obat Keluar, konfirmasi status Resep, Laporan, Master Data |
|
||||
| **Semua** | Dashboard, Monitoring Kadaluarsa, lihat Resep, Profil |
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Tech Stack
|
||||
|
||||
| Komponen | Teknologi |
|
||||
|----------|-----------|
|
||||
| Backend | Laravel 12, PHP 8.2+ |
|
||||
| Frontend | Blade Templates, Tailwind CSS v4, Alpine.js |
|
||||
| Grafik | Chart.js |
|
||||
| Database | MySQL 8.0+ |
|
||||
| Export | DomPDF, Maatwebsite Excel |
|
||||
| Testing | PHPUnit (159 tests) |
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ Instalasi
|
||||
|
||||
### Prasyarat
|
||||
- PHP ≥ 8.2
|
||||
- Composer
|
||||
- Node.js ≥ 18
|
||||
- MySQL ≥ 8.0
|
||||
|
||||
### Langkah Instalasi
|
||||
|
||||
```bash
|
||||
# 1. Clone repository
|
||||
git clone <repository-url>
|
||||
cd pencatatanobat
|
||||
|
||||
# 2. Install dependencies
|
||||
composer install
|
||||
npm install
|
||||
|
||||
# 3. Konfigurasi environment
|
||||
cp .env.example .env
|
||||
php artisan key:generate
|
||||
```
|
||||
|
||||
**4. Konfigurasi database di `.env`:**
|
||||
```env
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=pencatatanobat
|
||||
DB_USERNAME=root
|
||||
DB_PASSWORD=
|
||||
```
|
||||
|
||||
```bash
|
||||
# 5. Migrasi & seeder
|
||||
php artisan migrate --seed
|
||||
|
||||
# 6. Build assets
|
||||
npm run build
|
||||
|
||||
# 7. Jalankan server
|
||||
php artisan serve
|
||||
```
|
||||
|
||||
Akses aplikasi di `http://127.0.0.1:8000`
|
||||
|
||||
---
|
||||
|
||||
## 🔑 Akun Default
|
||||
|
||||
| Email | Password | Role |
|
||||
|-------|----------|------|
|
||||
| `dokter@dokter.com` | `password` | Dokter |
|
||||
| `admin@admin.com` | `password` | Apoteker |
|
||||
| `superadmin@meddata.com` | `password` | Superadmin |
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Testing
|
||||
|
||||
Aplikasi memiliki **159 test** (unit + feature) yang mencakup semua controller dan model utama.
|
||||
|
||||
```bash
|
||||
# Jalankan semua test
|
||||
php artisan test
|
||||
|
||||
# Hanya unit test
|
||||
php artisan test --testsuite=Unit
|
||||
|
||||
# Hanya feature test
|
||||
php artisan test --testsuite=Feature
|
||||
```
|
||||
|
||||
> **Catatan:** Test menggunakan SQLite in-memory via custom `DatabaseTestCase` untuk menghindari konflik dengan migrasi MySQL-specific.
|
||||
|
||||
---
|
||||
|
||||
## 📁 Struktur Direktori
|
||||
|
||||
```
|
||||
pencatatanobat/
|
||||
├── app/
|
||||
│ ├── Exports/ # Export Excel (Maatwebsite)
|
||||
│ ├── Http/
|
||||
│ │ ├── Controllers/ # DashboardController, ObatMasuk, ObatKeluar,
|
||||
│ │ │ # Resep, Kadaluarsa, Laporan, Kategori, Satuan
|
||||
│ │ └── Middleware/
|
||||
│ │ └── CheckRole.php # Middleware role-based access
|
||||
│ └── Models/ # User, ObatMasuk, ObatKeluar, Resep,
|
||||
│ # ResepItem, Kategori, Satuan
|
||||
├── database/
|
||||
│ ├── migrations/ # Migrasi MySQL
|
||||
│ ├── migrations/safe/ # Migrasi SQLite-compatible (untuk testing)
|
||||
│ └── seeders/
|
||||
├── resources/views/
|
||||
│ ├── dashboard/
|
||||
│ ├── obat-masuk/
|
||||
│ ├── obat-keluar/
|
||||
│ ├── resep/
|
||||
│ ├── kadaluarsa/
|
||||
│ ├── laporan/
|
||||
│ ├── kategori/
|
||||
│ ├── satuan/
|
||||
│ └── layouts/
|
||||
├── routes/
|
||||
│ └── web.php
|
||||
└── tests/
|
||||
├── DatabaseTestCase.php # Base class dengan SQLite-compatible schema
|
||||
├── Unit/ # Model unit tests
|
||||
└── Feature/ # Controller feature tests
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Skema Warna
|
||||
|
||||
| Komponen | Hex |
|
||||
|----------|-----|
|
||||
| Sidebar | `#4A538F` |
|
||||
| Background Konten | `#F4F6FF` |
|
||||
| Teks Utama | `#2F347A` |
|
||||
| Badge Aman | `#1F9254` |
|
||||
| Badge Waspada | `#B78103` |
|
||||
| Badge Awas | `#C0392B` |
|
||||
|
||||
---
|
||||
|
||||
## 📝 Lisensi
|
||||
|
||||
Proyek ini dikembangkan untuk keperluan internal Puskesmas Doko.
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
namespace App\Exports;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Maatwebsite\Excel\Concerns\FromCollection;
|
||||
use Maatwebsite\Excel\Concerns\WithHeadings;
|
||||
use Maatwebsite\Excel\Concerns\WithMapping;
|
||||
|
||||
class ObatKeluarExport implements FromCollection, WithHeadings, WithMapping
|
||||
{
|
||||
protected $startDate;
|
||||
protected $endDate;
|
||||
|
||||
public function __construct($startDate, $endDate)
|
||||
{
|
||||
$this->startDate = $startDate;
|
||||
$this->endDate = $endDate;
|
||||
}
|
||||
|
||||
public function collection()
|
||||
{
|
||||
return DB::table('obat_keluars')
|
||||
->join('obat_masuks', 'obat_keluars.obat_masuk_id', '=', 'obat_masuks.id')
|
||||
->leftJoin('satuans', 'obat_masuks.satuan_id', '=', 'satuans.id')
|
||||
->whereNotIn('obat_keluars.status', ['proses', 'dibatalkan'])
|
||||
->whereBetween('obat_keluars.tanggal_pengeluaran', [$this->startDate, $this->endDate])
|
||||
->select(
|
||||
'obat_keluars.nama_obat',
|
||||
'satuans.nama as satuan',
|
||||
DB::raw('SUM(obat_keluars.jumlah) as total_jumlah')
|
||||
)
|
||||
->groupBy('obat_keluars.nama_obat', 'satuans.nama')
|
||||
->orderBy('obat_keluars.nama_obat')
|
||||
->get();
|
||||
}
|
||||
|
||||
public function headings(): array
|
||||
{
|
||||
return [
|
||||
'Nama Obat',
|
||||
'Satuan',
|
||||
'Total Jumlah Keluar',
|
||||
];
|
||||
}
|
||||
|
||||
public function map($row): array
|
||||
{
|
||||
return [
|
||||
$row->nama_obat ?? 'N/A',
|
||||
$row->satuan ?? '-',
|
||||
$row->total_jumlah,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
namespace App\Exports;
|
||||
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Maatwebsite\Excel\Concerns\FromCollection;
|
||||
use Maatwebsite\Excel\Concerns\WithHeadings;
|
||||
use Maatwebsite\Excel\Concerns\WithMapping;
|
||||
|
||||
class ObatMasukExport implements FromCollection, WithHeadings, WithMapping
|
||||
{
|
||||
protected $startDate;
|
||||
protected $endDate;
|
||||
|
||||
public function __construct($startDate, $endDate)
|
||||
{
|
||||
$this->startDate = $startDate;
|
||||
$this->endDate = $endDate;
|
||||
}
|
||||
|
||||
public function collection()
|
||||
{
|
||||
return DB::table('obat_masuks')
|
||||
->join('satuans', 'obat_masuks.satuan_id', '=', 'satuans.id')
|
||||
->whereBetween('tanggal_penerimaan', [$this->startDate, $this->endDate])
|
||||
->select(
|
||||
'obat_masuks.nama_obat',
|
||||
'satuans.nama as satuan',
|
||||
DB::raw('SUM(obat_masuks.stok) as total_jumlah')
|
||||
)
|
||||
->groupBy('obat_masuks.nama_obat', 'satuans.nama')
|
||||
->orderBy('obat_masuks.nama_obat')
|
||||
->get();
|
||||
}
|
||||
|
||||
public function headings(): array
|
||||
{
|
||||
return [
|
||||
'Nama Obat',
|
||||
'Satuan',
|
||||
'Total Jumlah Masuk',
|
||||
];
|
||||
}
|
||||
|
||||
public function map($row): array
|
||||
{
|
||||
return [
|
||||
$row->nama_obat ?? 'N/A',
|
||||
$row->satuan ?? '-',
|
||||
$row->total_jumlah,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Auth\LoginRequest;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class AuthenticatedSessionController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display the login view.
|
||||
*/
|
||||
public function create(): View
|
||||
{
|
||||
return view('auth.login');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming authentication request.
|
||||
*/
|
||||
public function store(LoginRequest $request): RedirectResponse
|
||||
{
|
||||
$request->authenticate();
|
||||
|
||||
$request->session()->regenerate();
|
||||
|
||||
return redirect()->intended(route('dashboard', absolute: false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy an authenticated session.
|
||||
*/
|
||||
public function destroy(Request $request): RedirectResponse
|
||||
{
|
||||
Auth::guard('web')->logout();
|
||||
|
||||
$request->session()->invalidate();
|
||||
|
||||
$request->session()->regenerateToken();
|
||||
|
||||
return redirect('/');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class ConfirmablePasswordController extends Controller
|
||||
{
|
||||
/**
|
||||
* Show the confirm password view.
|
||||
*/
|
||||
public function show(): View
|
||||
{
|
||||
return view('auth.confirm-password');
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm the user's password.
|
||||
*/
|
||||
public function store(Request $request): RedirectResponse
|
||||
{
|
||||
if (! Auth::guard('web')->validate([
|
||||
'email' => $request->user()->email,
|
||||
'password' => $request->password,
|
||||
])) {
|
||||
throw ValidationException::withMessages([
|
||||
'password' => __('auth.password'),
|
||||
]);
|
||||
}
|
||||
|
||||
$request->session()->put('auth.password_confirmed_at', time());
|
||||
|
||||
return redirect()->intended(route('dashboard', absolute: false));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class EmailVerificationNotificationController extends Controller
|
||||
{
|
||||
/**
|
||||
* Send a new email verification notification.
|
||||
*/
|
||||
public function store(Request $request): RedirectResponse
|
||||
{
|
||||
if ($request->user()->hasVerifiedEmail()) {
|
||||
return redirect()->intended(route('dashboard', absolute: false));
|
||||
}
|
||||
|
||||
$request->user()->sendEmailVerificationNotification();
|
||||
|
||||
return back()->with('status', 'verification-link-sent');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class EmailVerificationPromptController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display the email verification prompt.
|
||||
*/
|
||||
public function __invoke(Request $request): RedirectResponse|View
|
||||
{
|
||||
return $request->user()->hasVerifiedEmail()
|
||||
? redirect()->intended(route('dashboard', absolute: false))
|
||||
: view('auth.verify-email');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\User;
|
||||
use Illuminate\Auth\Events\PasswordReset;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\Rules;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class NewPasswordController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display the password reset view.
|
||||
*/
|
||||
public function create(Request $request): View
|
||||
{
|
||||
return view('auth.reset-password', ['request' => $request]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming new password request.
|
||||
*
|
||||
* @throws \Illuminate\Validation\ValidationException
|
||||
*/
|
||||
public function store(Request $request): RedirectResponse
|
||||
{
|
||||
$request->validate([
|
||||
'token' => ['required'],
|
||||
'email' => ['required', 'email'],
|
||||
'password' => ['required', 'confirmed', Rules\Password::defaults()],
|
||||
]);
|
||||
|
||||
// Here we will attempt to reset the user's password. If it is successful we
|
||||
// will update the password on an actual user model and persist it to the
|
||||
// database. Otherwise we will parse the error and return the response.
|
||||
$status = Password::reset(
|
||||
$request->only('email', 'password', 'password_confirmation', 'token'),
|
||||
function (User $user) use ($request) {
|
||||
$user->forceFill([
|
||||
'password' => Hash::make($request->password),
|
||||
'remember_token' => Str::random(60),
|
||||
])->save();
|
||||
|
||||
event(new PasswordReset($user));
|
||||
}
|
||||
);
|
||||
|
||||
// If the password was successfully reset, we will redirect the user back to
|
||||
// the application's home authenticated view. If there is an error we can
|
||||
// redirect them back to where they came from with their error message.
|
||||
return $status == Password::PASSWORD_RESET
|
||||
? redirect()->route('login')->with('status', __($status))
|
||||
: back()->withInput($request->only('email'))
|
||||
->withErrors(['email' => __($status)]);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Validation\Rules\Password;
|
||||
|
||||
class PasswordController extends Controller
|
||||
{
|
||||
/**
|
||||
* Update the user's password.
|
||||
*/
|
||||
public function update(Request $request): RedirectResponse
|
||||
{
|
||||
$validated = $request->validateWithBag('updatePassword', [
|
||||
'current_password' => ['required', 'current_password'],
|
||||
'password' => ['required', Password::defaults(), 'confirmed'],
|
||||
]);
|
||||
|
||||
$request->user()->update([
|
||||
'password' => Hash::make($validated['password']),
|
||||
]);
|
||||
|
||||
return back()->with('status', 'password-updated');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class PasswordResetLinkController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display the password reset link request view.
|
||||
*/
|
||||
public function create(): View
|
||||
{
|
||||
return view('auth.forgot-password');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming password reset link request.
|
||||
*
|
||||
* @throws \Illuminate\Validation\ValidationException
|
||||
*/
|
||||
public function store(Request $request): RedirectResponse
|
||||
{
|
||||
$request->validate([
|
||||
'email' => ['required', 'email'],
|
||||
]);
|
||||
|
||||
// We will send the password reset link to this user. Once we have attempted
|
||||
// to send the link, we will examine the response then see the message we
|
||||
// need to show to the user. Finally, we'll send out a proper response.
|
||||
$status = Password::sendResetLink(
|
||||
$request->only('email')
|
||||
);
|
||||
|
||||
return $status == Password::RESET_LINK_SENT
|
||||
? back()->with('status', __($status))
|
||||
: back()->withInput($request->only('email'))
|
||||
->withErrors(['email' => __($status)]);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\User;
|
||||
use Illuminate\Auth\Events\Registered;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Validation\Rules;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class RegisteredUserController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display the registration view.
|
||||
*/
|
||||
public function create(): View
|
||||
{
|
||||
return view('auth.register');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming registration request.
|
||||
*
|
||||
* @throws \Illuminate\Validation\ValidationException
|
||||
*/
|
||||
public function store(Request $request): RedirectResponse
|
||||
{
|
||||
$request->validate([
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
'email' => ['required', 'string', 'lowercase', 'email', 'max:255', 'unique:'.User::class],
|
||||
'password' => ['required', 'confirmed', Rules\Password::defaults()],
|
||||
]);
|
||||
|
||||
$user = User::create([
|
||||
'name' => $request->name,
|
||||
'email' => $request->email,
|
||||
'password' => Hash::make($request->password),
|
||||
]);
|
||||
|
||||
event(new Registered($user));
|
||||
|
||||
Auth::login($user);
|
||||
|
||||
return redirect(route('dashboard', absolute: false));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Auth\Events\Verified;
|
||||
use Illuminate\Foundation\Auth\EmailVerificationRequest;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
|
||||
class VerifyEmailController extends Controller
|
||||
{
|
||||
/**
|
||||
* Mark the authenticated user's email address as verified.
|
||||
*/
|
||||
public function __invoke(EmailVerificationRequest $request): RedirectResponse
|
||||
{
|
||||
if ($request->user()->hasVerifiedEmail()) {
|
||||
return redirect()->intended(route('dashboard', absolute: false).'?verified=1');
|
||||
}
|
||||
|
||||
if ($request->user()->markEmailAsVerified()) {
|
||||
event(new Verified($request->user()));
|
||||
}
|
||||
|
||||
return redirect()->intended(route('dashboard', absolute: false).'?verified=1');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
abstract class Controller
|
||||
{
|
||||
//
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Obat;
|
||||
use App\Models\ObatMasuk;
|
||||
use App\Models\ObatKeluar;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class DashboardController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
// Get filter month and year for chart (default to current month)
|
||||
$filterMonth = $request->get('chart_month', now()->month);
|
||||
$filterYear = $request->get('chart_year', now()->year);
|
||||
|
||||
// Create date object for the selected month
|
||||
$selectedDate = Carbon::createFromDate($filterYear, $filterMonth, 1);
|
||||
|
||||
// Statistics
|
||||
$totalJenisObat = ObatMasuk::count();
|
||||
$obatMasukBulanIni = ObatMasuk::whereMonth('tanggal_penerimaan', now()->month)
|
||||
->whereYear('tanggal_penerimaan', now()->year)
|
||||
->count();
|
||||
$obatKeluarBulanIni = ObatKeluar::whereMonth('tanggal_pengeluaran', now()->month)
|
||||
->whereYear('tanggal_pengeluaran', now()->year)
|
||||
->count();
|
||||
$kadaluarsaDekat = ObatMasuk::where('tanggal_kadaluarsa', '<=', now()->addMonths(4))
|
||||
->where('tanggal_kadaluarsa', '>=', now())
|
||||
->count();
|
||||
|
||||
// Chart data - daily data for selected month (line chart)
|
||||
$daysInMonth = $selectedDate->daysInMonth;
|
||||
$labels = [];
|
||||
$obatMasukData = [];
|
||||
$obatKeluarData = [];
|
||||
|
||||
for ($i = 1; $i <= $daysInMonth; $i++) {
|
||||
$date = Carbon::create($filterYear, $filterMonth, $i);
|
||||
$labels[] = $i;
|
||||
|
||||
$obatMasukData[] = ObatMasuk::whereDate('tanggal_penerimaan', $date)->count();
|
||||
$obatKeluarData[] = ObatKeluar::whereDate('tanggal_pengeluaran', $date)->count();
|
||||
}
|
||||
|
||||
// Generate month options for filter (last 12 months)
|
||||
$monthOptions = [];
|
||||
for ($i = 0; $i < 12; $i++) {
|
||||
$date = now()->subMonths($i);
|
||||
$monthOptions[] = [
|
||||
'value' => $date->format('Y-m'),
|
||||
'label' => $date->translatedFormat('F Y'),
|
||||
'month' => $date->month,
|
||||
'year' => $date->year,
|
||||
];
|
||||
}
|
||||
|
||||
// Expiring medicines
|
||||
$obatKadaluarsa = ObatMasuk::where('tanggal_kadaluarsa', '<=', now()->addMonths(4))
|
||||
->with('obat')
|
||||
->orderBy('tanggal_kadaluarsa', 'asc')
|
||||
->limit(10)
|
||||
->get();
|
||||
|
||||
return view('dashboard.index', compact(
|
||||
'totalJenisObat',
|
||||
'obatMasukBulanIni',
|
||||
'obatKeluarBulanIni',
|
||||
'kadaluarsaDekat',
|
||||
'labels',
|
||||
'obatMasukData',
|
||||
'obatKeluarData',
|
||||
'obatKadaluarsa',
|
||||
'monthOptions',
|
||||
'filterMonth',
|
||||
'filterYear',
|
||||
'selectedDate'
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\ObatMasuk;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class KadaluarsaController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
// Only show medicines that are expired (minus days) or expiring within 60 days (awas/waspada)
|
||||
$query = ObatMasuk::with(['obat.kategori'])
|
||||
->where('tanggal_kadaluarsa', '<=', now()->addMonths(4));
|
||||
|
||||
// Filter by remaining days
|
||||
$filter = $request->get('filter', 'all');
|
||||
|
||||
if ($filter === 'expired') {
|
||||
// Only expired (minus days)
|
||||
$query->where('tanggal_kadaluarsa', '<', now());
|
||||
} elseif ($filter === '30') {
|
||||
// Awas: expired or <= 30 days remaining
|
||||
$query->where('tanggal_kadaluarsa', '<=', now()->addDays(30));
|
||||
} elseif ($filter === '120') {
|
||||
// Waspada: expired or <= 4 months remaining
|
||||
$query->where('tanggal_kadaluarsa', '<=', now()->addMonths(4));
|
||||
}
|
||||
|
||||
$obatKadaluarsa = $query->orderBy('tanggal_kadaluarsa', 'asc')->paginate(15);
|
||||
|
||||
return view('kadaluarsa.index', compact('obatKadaluarsa', 'filter'));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Kategori;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class KategoriController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
$kategoris = Kategori::orderBy('nama')->paginate(10);
|
||||
return view('kategori.index', compact('kategoris'));
|
||||
}
|
||||
|
||||
public function create()
|
||||
{
|
||||
return view('kategori.create');
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'nama' => 'required|string|max:100|unique:kategoris,nama',
|
||||
'keterangan' => 'nullable|string|max:255',
|
||||
]);
|
||||
|
||||
Kategori::create($validated);
|
||||
|
||||
return redirect()->route('kategori.index')->with('success', 'Kategori berhasil ditambahkan');
|
||||
}
|
||||
|
||||
public function edit(Kategori $kategori)
|
||||
{
|
||||
return view('kategori.edit', compact('kategori'));
|
||||
}
|
||||
|
||||
public function update(Request $request, Kategori $kategori)
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'nama' => 'required|string|max:100|unique:kategoris,nama,' . $kategori->id,
|
||||
'keterangan' => 'nullable|string|max:255',
|
||||
]);
|
||||
|
||||
$kategori->update($validated);
|
||||
|
||||
return redirect()->route('kategori.index')->with('success', 'Kategori berhasil diperbarui');
|
||||
}
|
||||
|
||||
public function destroy(Kategori $kategori)
|
||||
{
|
||||
$kategori->delete();
|
||||
return redirect()->route('kategori.index')->with('success', 'Kategori berhasil dihapus');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\ObatMasuk;
|
||||
use App\Models\ObatKeluar;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Barryvdh\DomPDF\Facade\Pdf;
|
||||
use Maatwebsite\Excel\Facades\Excel;
|
||||
use App\Exports\ObatMasukExport;
|
||||
use App\Exports\ObatKeluarExport;
|
||||
|
||||
class LaporanController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$jenis = $request->get('jenis', 'masuk');
|
||||
$tanggalMulai = $request->get('tanggal_mulai', now()->startOfMonth()->format('Y-m-d'));
|
||||
$tanggalAkhir = $request->get('tanggal_akhir', now()->endOfMonth()->format('Y-m-d'));
|
||||
|
||||
if ($jenis === 'masuk') {
|
||||
$data = ObatMasuk::with(['kategori', 'satuan', 'supplier'])
|
||||
->whereBetween('tanggal_penerimaan', [$tanggalMulai, $tanggalAkhir])
|
||||
->orderBy('tanggal_penerimaan', 'desc')
|
||||
->paginate(15);
|
||||
} else {
|
||||
$data = ObatKeluar::whereNotIn('status', ['proses', 'dibatalkan'])
|
||||
->whereBetween('tanggal_pengeluaran', [$tanggalMulai, $tanggalAkhir])
|
||||
->orderBy('tanggal_pengeluaran', 'desc')
|
||||
->paginate(15);
|
||||
}
|
||||
|
||||
return view('laporan.index', compact('data', 'jenis', 'tanggalMulai', 'tanggalAkhir'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to get aggregated (grouped by nama_obat) data for exports.
|
||||
*/
|
||||
private function getAggregatedData(string $jenis, string $tanggalMulai, string $tanggalAkhir)
|
||||
{
|
||||
if ($jenis === 'masuk') {
|
||||
return DB::table('obat_masuks')
|
||||
->join('satuans', 'obat_masuks.satuan_id', '=', 'satuans.id')
|
||||
->whereBetween('tanggal_penerimaan', [$tanggalMulai, $tanggalAkhir])
|
||||
->select(
|
||||
'obat_masuks.nama_obat',
|
||||
'satuans.nama as satuan',
|
||||
DB::raw('SUM(obat_masuks.stok) as total_jumlah')
|
||||
)
|
||||
->groupBy('obat_masuks.nama_obat', 'satuans.nama')
|
||||
->orderBy('obat_masuks.nama_obat')
|
||||
->get();
|
||||
} else {
|
||||
return DB::table('obat_keluars')
|
||||
->join('obat_masuks', 'obat_keluars.obat_masuk_id', '=', 'obat_masuks.id')
|
||||
->leftJoin('satuans', 'obat_masuks.satuan_id', '=', 'satuans.id')
|
||||
->whereNotIn('obat_keluars.status', ['proses', 'dibatalkan'])
|
||||
->whereBetween('obat_keluars.tanggal_pengeluaran', [$tanggalMulai, $tanggalAkhir])
|
||||
->select(
|
||||
'obat_keluars.nama_obat',
|
||||
'satuans.nama as satuan',
|
||||
DB::raw('SUM(obat_keluars.jumlah) as total_jumlah')
|
||||
)
|
||||
->groupBy('obat_keluars.nama_obat', 'satuans.nama')
|
||||
->orderBy('obat_keluars.nama_obat')
|
||||
->get();
|
||||
}
|
||||
}
|
||||
|
||||
public function exportPdf(Request $request)
|
||||
{
|
||||
$jenis = $request->get('jenis', 'masuk');
|
||||
$tanggalMulai = $request->get('tanggal_mulai', now()->startOfMonth()->format('Y-m-d'));
|
||||
$tanggalAkhir = $request->get('tanggal_akhir', now()->endOfMonth()->format('Y-m-d'));
|
||||
|
||||
$title = $jenis === 'masuk' ? 'Laporan Obat Masuk' : 'Laporan Obat Keluar';
|
||||
$data = $this->getAggregatedData($jenis, $tanggalMulai, $tanggalAkhir);
|
||||
|
||||
$pdf = Pdf::loadView('laporan.pdf', compact('data', 'jenis', 'title', 'tanggalMulai', 'tanggalAkhir'));
|
||||
$filename = "laporan-obat-{$jenis}-" . date('Y-m-d') . ".pdf";
|
||||
|
||||
return $pdf->download($filename);
|
||||
}
|
||||
|
||||
public function exportExcel(Request $request)
|
||||
{
|
||||
$jenis = $request->get('jenis', 'masuk');
|
||||
$tanggalMulai = $request->get('tanggal_mulai', now()->startOfMonth()->format('Y-m-d'));
|
||||
$tanggalAkhir = $request->get('tanggal_akhir', now()->endOfMonth()->format('Y-m-d'));
|
||||
|
||||
$filename = "laporan-obat-{$jenis}-" . date('Y-m-d') . ".xlsx";
|
||||
|
||||
if ($jenis === 'masuk') {
|
||||
return Excel::download(new ObatMasukExport($tanggalMulai, $tanggalAkhir), $filename);
|
||||
} else {
|
||||
return Excel::download(new ObatKeluarExport($tanggalMulai, $tanggalAkhir), $filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,216 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\ObatMasuk;
|
||||
use App\Models\ObatKeluar;
|
||||
use App\Models\Kategori;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class ObatKeluarController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$query = ObatKeluar::with(['obatMasuk.kategori']);
|
||||
|
||||
// Search
|
||||
if ($request->filled('search')) {
|
||||
$search = $request->search;
|
||||
$query->where(function($q) use ($search) {
|
||||
$q->where('nama_obat', 'like', "%{$search}%")
|
||||
->orWhere('kode_batch', 'like', "%{$search}%");
|
||||
});
|
||||
}
|
||||
|
||||
// Filter by status
|
||||
if ($request->filled('status')) {
|
||||
$query->where('status', $request->status);
|
||||
}
|
||||
|
||||
$obatKeluars = $query->orderBy('tanggal_pengeluaran', 'desc')->paginate(10);
|
||||
$kategoris = Kategori::all();
|
||||
|
||||
// Get filter month and year (default to current month)
|
||||
$filterMonth = $request->get('chart_month', now()->month);
|
||||
$filterYear = $request->get('chart_year', now()->year);
|
||||
|
||||
// Create date object for the selected month
|
||||
$selectedDate = Carbon::createFromDate($filterYear, $filterMonth, 1);
|
||||
|
||||
// Pie chart data - Medicine trend (top 5 medicines by usage) for selected month
|
||||
$medicineTrend = ObatKeluar::selectRaw('nama_obat, SUM(jumlah) as total_jumlah')
|
||||
->whereMonth('tanggal_pengeluaran', $filterMonth)
|
||||
->whereYear('tanggal_pengeluaran', $filterYear)
|
||||
->groupBy('nama_obat')
|
||||
->orderByDesc('total_jumlah')
|
||||
->limit(5)
|
||||
->get();
|
||||
|
||||
$pieLabels = $medicineTrend->pluck('nama_obat')->toArray();
|
||||
$pieData = $medicineTrend->pluck('total_jumlah')->toArray();
|
||||
$totalUsage = array_sum($pieData);
|
||||
|
||||
// Generate month options for filter (last 12 months)
|
||||
$monthOptions = [];
|
||||
for ($i = 0; $i < 12; $i++) {
|
||||
$date = now()->subMonths($i);
|
||||
$monthOptions[] = [
|
||||
'value' => $date->format('Y-m'),
|
||||
'label' => $date->translatedFormat('F Y'),
|
||||
'month' => $date->month,
|
||||
'year' => $date->year,
|
||||
];
|
||||
}
|
||||
|
||||
return view('obat-keluar.index', compact(
|
||||
'obatKeluars',
|
||||
'kategoris',
|
||||
'pieLabels',
|
||||
'pieData',
|
||||
'totalUsage',
|
||||
'monthOptions',
|
||||
'filterMonth',
|
||||
'filterYear',
|
||||
'selectedDate'
|
||||
));
|
||||
}
|
||||
|
||||
public function create()
|
||||
{
|
||||
$kategoris = Kategori::all();
|
||||
// Ambil obat dari tabel obat_masuks yang masih ada stoknya
|
||||
$obats = ObatMasuk::where('stok', '>', 0)
|
||||
->where('tanggal_kadaluarsa', '>=', now())
|
||||
->with('kategori')
|
||||
->orderBy('nama_obat')
|
||||
->get();
|
||||
|
||||
return view('obat-keluar.create', compact('kategoris', 'obats'));
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'obat_masuk_id' => 'required|exists:obat_masuks,id',
|
||||
'kode_batch' => 'required|string|max:50',
|
||||
'barcode' => 'nullable|string|max:100',
|
||||
'sumber_dana' => 'nullable|string|max:200',
|
||||
'jumlah' => 'required|integer|min:1',
|
||||
'harga' => 'nullable|numeric|min:0',
|
||||
'harga_total' => 'nullable|numeric|min:0',
|
||||
'tujuan_pemakaian' => 'required|string|max:200',
|
||||
'tanggal_kadaluarsa' => 'required|date',
|
||||
'tanggal_pengeluaran' => 'required|date',
|
||||
'no_pengeluaran' => 'nullable|string|max:50',
|
||||
'nama_petugas' => 'required|string|max:100',
|
||||
'nama_penerima' => 'required|string|max:100',
|
||||
'catatan' => 'nullable|string',
|
||||
'status' => 'nullable|in:proses,selesai,dibatalkan',
|
||||
]);
|
||||
|
||||
// Cek stok tersedia
|
||||
$obatMasuk = ObatMasuk::findOrFail($validated['obat_masuk_id']);
|
||||
|
||||
if ($obatMasuk->stok < $validated['jumlah']) {
|
||||
return back()->withErrors(['jumlah' => 'Jumlah melebihi stok yang tersedia (' . $obatMasuk->stok . ')'])->withInput();
|
||||
}
|
||||
|
||||
DB::transaction(function () use ($validated, $obatMasuk) {
|
||||
// Simpan nama obat dari obat masuk
|
||||
$validated['nama_obat'] = $obatMasuk->nama_obat;
|
||||
$validated['user_id'] = auth()->id();
|
||||
$validated['status'] = $validated['status'] ?? 'proses';
|
||||
|
||||
// Buat obat keluar
|
||||
ObatKeluar::create($validated);
|
||||
|
||||
// Kurangi stok obat masuk
|
||||
$obatMasuk->decrement('stok', $validated['jumlah']);
|
||||
});
|
||||
|
||||
return redirect()->route('obat-keluar.index')->with('success', 'Data obat keluar berhasil ditambahkan dan stok obat masuk telah dikurangi');
|
||||
}
|
||||
|
||||
public function show(ObatKeluar $obatKeluar)
|
||||
{
|
||||
$obatKeluar->load(['obatMasuk.kategori', 'user']);
|
||||
return view('obat-keluar.show', compact('obatKeluar'));
|
||||
}
|
||||
|
||||
public function edit(ObatKeluar $obatKeluar)
|
||||
{
|
||||
$kategoris = Kategori::all();
|
||||
$obats = ObatMasuk::where(function ($q) {
|
||||
$q->where('stok', '>', 0)
|
||||
->where('tanggal_kadaluarsa', '>=', now());
|
||||
})
|
||||
->orWhere('id', $obatKeluar->obat_masuk_id)
|
||||
->with('kategori')
|
||||
->orderBy('nama_obat')
|
||||
->get();
|
||||
|
||||
return view('obat-keluar.edit', compact('obatKeluar', 'kategoris', 'obats'));
|
||||
}
|
||||
|
||||
public function update(Request $request, ObatKeluar $obatKeluar)
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'obat_masuk_id' => 'required|exists:obat_masuks,id',
|
||||
'kode_batch' => 'required|string|max:50',
|
||||
'barcode' => 'nullable|string|max:100',
|
||||
'sumber_dana' => 'nullable|string|max:200',
|
||||
'jumlah' => 'required|integer|min:1',
|
||||
'harga' => 'nullable|numeric|min:0',
|
||||
'harga_total' => 'nullable|numeric|min:0',
|
||||
'tujuan_pemakaian' => 'required|string|max:200',
|
||||
'tanggal_kadaluarsa' => 'required|date',
|
||||
'tanggal_pengeluaran' => 'required|date',
|
||||
'no_pengeluaran' => 'nullable|string|max:50',
|
||||
'nama_petugas' => 'required|string|max:100',
|
||||
'nama_penerima' => 'required|string|max:100',
|
||||
'catatan' => 'nullable|string',
|
||||
'status' => 'nullable|in:proses,selesai,dibatalkan',
|
||||
]);
|
||||
|
||||
$obatMasuk = ObatMasuk::findOrFail($validated['obat_masuk_id']);
|
||||
|
||||
// Hitung selisih jumlah
|
||||
$selisih = $validated['jumlah'] - $obatKeluar->jumlah;
|
||||
|
||||
if ($selisih > 0 && $obatMasuk->stok < $selisih) {
|
||||
return back()->withErrors(['jumlah' => 'Jumlah melebihi stok yang tersedia'])->withInput();
|
||||
}
|
||||
|
||||
DB::transaction(function () use ($validated, $obatKeluar, $obatMasuk, $selisih) {
|
||||
// Update nama obat
|
||||
$validated['nama_obat'] = $obatMasuk->nama_obat;
|
||||
|
||||
// Update stok
|
||||
if ($selisih > 0) {
|
||||
$obatMasuk->decrement('stok', $selisih);
|
||||
} elseif ($selisih < 0) {
|
||||
$obatMasuk->increment('stok', abs($selisih));
|
||||
}
|
||||
|
||||
$obatKeluar->update($validated);
|
||||
});
|
||||
|
||||
return redirect()->route('obat-keluar.index')->with('success', 'Data obat keluar berhasil diperbarui');
|
||||
}
|
||||
|
||||
public function destroy(ObatKeluar $obatKeluar)
|
||||
{
|
||||
DB::transaction(function () use ($obatKeluar) {
|
||||
// Kembalikan stok ke obat masuk
|
||||
if ($obatKeluar->obatMasuk) {
|
||||
$obatKeluar->obatMasuk->increment('stok', $obatKeluar->jumlah);
|
||||
}
|
||||
|
||||
$obatKeluar->delete();
|
||||
});
|
||||
|
||||
return redirect()->route('obat-keluar.index')->with('success', 'Data obat keluar berhasil dihapus dan stok dikembalikan');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,166 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\ObatMasuk;
|
||||
use App\Models\Kategori;
|
||||
use App\Models\Satuan;
|
||||
use App\Models\Supplier;
|
||||
use Illuminate\Http\Request;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class ObatMasukController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$query = ObatMasuk::query();
|
||||
|
||||
// Search
|
||||
if ($request->filled('search')) {
|
||||
$search = $request->search;
|
||||
$query->where(function($q) use ($search) {
|
||||
$q->where('nama_obat', 'like', "%{$search}%")
|
||||
->orWhere('kode_batch', 'like', "%{$search}%");
|
||||
});
|
||||
}
|
||||
|
||||
// Filter by category
|
||||
if ($request->filled('kategori')) {
|
||||
$query->where('kategori_id', $request->kategori);
|
||||
}
|
||||
|
||||
// Filter by status
|
||||
if ($request->filled('status')) {
|
||||
if ($request->status === 'tersedia') {
|
||||
$query->where('stok', '>', 0);
|
||||
} else if ($request->status === 'habis') {
|
||||
$query->where('stok', 0);
|
||||
}
|
||||
}
|
||||
|
||||
$obatMasuks = $query->with(['kategori', 'satuan', 'supplier'])
|
||||
->orderBy('tanggal_penerimaan', 'desc')
|
||||
->paginate(10);
|
||||
$kategoris = Kategori::all();
|
||||
|
||||
// Get filter month and year (default to current month)
|
||||
$filterMonth = $request->get('chart_month', now()->month);
|
||||
$filterYear = $request->get('chart_year', now()->year);
|
||||
|
||||
// Create date object for the selected month
|
||||
$selectedDate = Carbon::createFromDate($filterYear, $filterMonth, 1);
|
||||
|
||||
// Pie chart data - Medicine trend (top 5 medicines by stock received) for selected month
|
||||
$medicineTrend = ObatMasuk::selectRaw('nama_obat, SUM(stok) as total_stok')
|
||||
->whereMonth('tanggal_penerimaan', $filterMonth)
|
||||
->whereYear('tanggal_penerimaan', $filterYear)
|
||||
->groupBy('nama_obat')
|
||||
->orderByDesc('total_stok')
|
||||
->limit(5)
|
||||
->get();
|
||||
|
||||
$pieLabels = $medicineTrend->pluck('nama_obat')->toArray();
|
||||
$pieData = $medicineTrend->pluck('total_stok')->toArray();
|
||||
$totalStock = array_sum($pieData);
|
||||
|
||||
// Generate month options for filter (last 12 months)
|
||||
$monthOptions = [];
|
||||
for ($i = 0; $i < 12; $i++) {
|
||||
$date = now()->subMonths($i);
|
||||
$monthOptions[] = [
|
||||
'value' => $date->format('Y-m'),
|
||||
'label' => $date->translatedFormat('F Y'),
|
||||
'month' => $date->month,
|
||||
'year' => $date->year,
|
||||
];
|
||||
}
|
||||
|
||||
return view('obat-masuk.index', compact(
|
||||
'obatMasuks',
|
||||
'kategoris',
|
||||
'pieLabels',
|
||||
'pieData',
|
||||
'totalStock',
|
||||
'monthOptions',
|
||||
'filterMonth',
|
||||
'filterYear',
|
||||
'selectedDate'
|
||||
));
|
||||
}
|
||||
|
||||
public function create()
|
||||
{
|
||||
$kategoris = Kategori::orderBy('nama')->get();
|
||||
$satuans = Satuan::orderBy('nama')->get();
|
||||
$suppliers = Supplier::orderBy('nama')->get();
|
||||
|
||||
return view('obat-masuk.create', compact('kategoris', 'satuans', 'suppliers'));
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'nama_obat' => 'required|string|max:200',
|
||||
'kategori_id' => 'required|exists:kategoris,id',
|
||||
'satuan_id' => 'required|exists:satuans,id',
|
||||
'sumber_dana' => 'nullable|string|max:200',
|
||||
'kode_batch' => 'required|string|max:50',
|
||||
'barcode' => 'nullable|string|max:100',
|
||||
'stok' => 'required|integer|min:1',
|
||||
'tanggal_penerimaan' => 'required|date',
|
||||
'tanggal_kadaluarsa' => 'required|date|after:tanggal_penerimaan',
|
||||
'no_faktur' => 'nullable|string|max:50',
|
||||
'no_sbbk' => 'nullable|string|max:100',
|
||||
'catatan' => 'nullable|string',
|
||||
]);
|
||||
|
||||
$validated['user_id'] = auth()->id();
|
||||
|
||||
ObatMasuk::create($validated);
|
||||
|
||||
return redirect()->route('obat-masuk.index')->with('success', 'Data obat masuk berhasil ditambahkan');
|
||||
}
|
||||
|
||||
public function show(ObatMasuk $obatMasuk)
|
||||
{
|
||||
$obatMasuk->load(['kategori', 'satuan', 'supplier', 'user']);
|
||||
return view('obat-masuk.show', compact('obatMasuk'));
|
||||
}
|
||||
|
||||
public function edit(ObatMasuk $obatMasuk)
|
||||
{
|
||||
$kategoris = Kategori::orderBy('nama')->get();
|
||||
$satuans = Satuan::orderBy('nama')->get();
|
||||
$suppliers = Supplier::orderBy('nama')->get();
|
||||
|
||||
return view('obat-masuk.edit', compact('obatMasuk', 'kategoris', 'satuans', 'suppliers'));
|
||||
}
|
||||
|
||||
public function update(Request $request, ObatMasuk $obatMasuk)
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'nama_obat' => 'required|string|max:200',
|
||||
'kategori_id' => 'required|exists:kategoris,id',
|
||||
'satuan_id' => 'required|exists:satuans,id',
|
||||
'sumber_dana' => 'nullable|string|max:200',
|
||||
'kode_batch' => 'required|string|max:50',
|
||||
'barcode' => 'nullable|string|max:100',
|
||||
'stok' => 'required|integer|min:0',
|
||||
'tanggal_penerimaan' => 'required|date',
|
||||
'tanggal_kadaluarsa' => 'required|date|after:tanggal_penerimaan',
|
||||
'no_faktur' => 'nullable|string|max:50',
|
||||
'no_sbbk' => 'nullable|string|max:100',
|
||||
'catatan' => 'nullable|string',
|
||||
]);
|
||||
|
||||
$obatMasuk->update($validated);
|
||||
|
||||
return redirect()->route('obat-masuk.index')->with('success', 'Data obat masuk berhasil diperbarui');
|
||||
}
|
||||
|
||||
public function destroy(ObatMasuk $obatMasuk)
|
||||
{
|
||||
$obatMasuk->delete();
|
||||
return redirect()->route('obat-masuk.index')->with('success', 'Data obat masuk berhasil dihapus');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Redirect;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class ProfileController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display the user's profile form.
|
||||
*/
|
||||
public function edit(Request $request): View
|
||||
{
|
||||
return view('profile.edit', [
|
||||
'user' => $request->user(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the user's profile information.
|
||||
*/
|
||||
public function update(Request $request): RedirectResponse
|
||||
{
|
||||
$user = $request->user();
|
||||
|
||||
// Handle photo-only upload form
|
||||
if ($request->input('_photo_only')) {
|
||||
$request->validate([
|
||||
'profile_photo' => ['required', 'image', 'max:2048'],
|
||||
]);
|
||||
|
||||
if ($user->profile_photo) {
|
||||
Storage::disk('public')->delete($user->profile_photo);
|
||||
}
|
||||
|
||||
$user->profile_photo = $request->file('profile_photo')->store('profile-photos', 'public');
|
||||
$user->save();
|
||||
|
||||
return Redirect::route('profile.edit')->with('status', 'profile-updated');
|
||||
}
|
||||
|
||||
// Handle full profile update
|
||||
$validated = $request->validate([
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
'nip' => ['nullable', 'string', 'max:50'],
|
||||
'email' => ['required', 'string', 'lowercase', 'email', 'max:255',
|
||||
\Illuminate\Validation\Rule::unique('users')->ignore($user->id)],
|
||||
'phone' => ['nullable', 'string', 'max:20'],
|
||||
'gender' => ['required', 'in:laki-laki,perempuan'],
|
||||
'address' => ['nullable', 'string', 'max:1000'],
|
||||
'division' => ['nullable', 'string', 'max:255'],
|
||||
'position' => ['nullable', 'string', 'max:255'],
|
||||
]);
|
||||
|
||||
$user->fill($validated);
|
||||
|
||||
if ($user->isDirty('email')) {
|
||||
$user->email_verified_at = null;
|
||||
}
|
||||
|
||||
$user->save();
|
||||
|
||||
return Redirect::route('profile.edit')->with('status', 'profile-updated');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete the user's account.
|
||||
*/
|
||||
public function destroy(Request $request): RedirectResponse
|
||||
{
|
||||
$request->validateWithBag('userDeletion', [
|
||||
'password' => ['required', 'current_password'],
|
||||
]);
|
||||
|
||||
$user = $request->user();
|
||||
|
||||
if ($user->profile_photo) {
|
||||
Storage::disk('public')->delete($user->profile_photo);
|
||||
}
|
||||
|
||||
Auth::logout();
|
||||
|
||||
$user->delete();
|
||||
|
||||
$request->session()->invalidate();
|
||||
$request->session()->regenerateToken();
|
||||
|
||||
return Redirect::to('/');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,382 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Resep;
|
||||
use App\Models\ResepItem;
|
||||
use App\Models\ObatMasuk;
|
||||
use App\Models\ObatKeluar;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class ResepController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the prescriptions.
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$query = Resep::with(['user', 'items']);
|
||||
|
||||
// Search
|
||||
if ($request->filled('search')) {
|
||||
$search = $request->search;
|
||||
$query->where(function($q) use ($search) {
|
||||
$q->where('no_resep', 'like', "%{$search}%")
|
||||
->orWhere('nama_pasien', 'like', "%{$search}%")
|
||||
->orWhere('no_rm', 'like', "%{$search}%");
|
||||
});
|
||||
}
|
||||
|
||||
// Filter by status
|
||||
if ($request->filled('status')) {
|
||||
$query->where('status', $request->status);
|
||||
}
|
||||
|
||||
$reseps = $query->orderBy('tanggal_resep', 'desc')->paginate(10);
|
||||
|
||||
return view('resep.index', compact('reseps'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new prescription.
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
// Get medicines with available stock
|
||||
$obats = ObatMasuk::where('stok', '>', 0)
|
||||
->where('tanggal_kadaluarsa', '>=', now())
|
||||
->with('kategori', 'satuan')
|
||||
->orderBy('nama_obat')
|
||||
->get();
|
||||
|
||||
return view('resep.create', compact('obats'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created prescription in storage.
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$validated = $request->validate([
|
||||
// Data Resep
|
||||
'nama_dokter' => 'required|string|max:100',
|
||||
'no_sip' => 'nullable|string|max:50',
|
||||
'tanggal_resep' => 'required|date',
|
||||
'jenis_penjamin' => 'required|in:umum,BPJS Kes,BPJS Naker,Jamkesmas/KIS,R. Inap',
|
||||
'jenis_layanan' => 'required|in:BP,KIA,Gigi,UGD,Lainnya',
|
||||
// Data Pasien
|
||||
'no_rm' => 'nullable|string|max:50',
|
||||
'nama_pasien' => 'required|string|max:100',
|
||||
'alamat_pasien' => 'nullable|string|max:255',
|
||||
'jenis_kelamin' => 'required|in:L,P',
|
||||
'umur_pasien' => 'required|integer|min:0|max:150',
|
||||
'berat_badan' => 'required|numeric|min:0|max:500',
|
||||
'diagnosa' => 'required|string',
|
||||
'catatan' => 'nullable|string',
|
||||
// Daftar Obat
|
||||
'items' => 'required|array|min:1',
|
||||
'items.*.obat_masuk_id' => 'required|exists:obat_masuks,id',
|
||||
'items.*.jumlah' => 'required|integer|min:1',
|
||||
'items.*.aturan_pakai' => 'nullable|string|max:255',
|
||||
]);
|
||||
|
||||
// Validate stock availability
|
||||
foreach ($validated['items'] as $item) {
|
||||
$obatMasuk = ObatMasuk::find($item['obat_masuk_id']);
|
||||
if ($obatMasuk->stok < $item['jumlah']) {
|
||||
return back()->withErrors([
|
||||
'items' => "Stok obat {$obatMasuk->nama_obat} tidak mencukupi. Tersedia: {$obatMasuk->stok}"
|
||||
])->withInput();
|
||||
}
|
||||
}
|
||||
|
||||
DB::transaction(function () use ($validated, $request) {
|
||||
// Create resep with status 'proses' (not 'selesai')
|
||||
$resep = Resep::create([
|
||||
'no_resep' => Resep::generateNoResep(),
|
||||
'user_id' => auth()->id(),
|
||||
'nama_dokter' => $validated['nama_dokter'],
|
||||
'no_sip' => $validated['no_sip'] ?? null,
|
||||
'jenis_penjamin' => $validated['jenis_penjamin'],
|
||||
'jenis_layanan' => $validated['jenis_layanan'],
|
||||
'no_rm' => $validated['no_rm'] ?? null,
|
||||
'nama_pasien' => $validated['nama_pasien'],
|
||||
'alamat_pasien' => $validated['alamat_pasien'] ?? null,
|
||||
'jenis_kelamin' => $validated['jenis_kelamin'],
|
||||
'umur_pasien' => $validated['umur_pasien'],
|
||||
'berat_badan' => $validated['berat_badan'],
|
||||
'tanggal_resep' => $validated['tanggal_resep'],
|
||||
'diagnosa' => $validated['diagnosa'],
|
||||
'catatan' => $validated['catatan'] ?? null,
|
||||
'status' => 'proses', // Changed from 'selesai' to 'proses'
|
||||
'is_read' => false,
|
||||
]);
|
||||
|
||||
// Create resep items and reduce stock
|
||||
foreach ($validated['items'] as $item) {
|
||||
$obatMasuk = ObatMasuk::find($item['obat_masuk_id']);
|
||||
|
||||
// Create resep item
|
||||
ResepItem::create([
|
||||
'resep_id' => $resep->id,
|
||||
'obat_masuk_id' => $item['obat_masuk_id'],
|
||||
'nama_obat' => $obatMasuk->nama_obat,
|
||||
'jumlah' => $item['jumlah'],
|
||||
'aturan_pakai' => $item['aturan_pakai'] ?? null,
|
||||
]);
|
||||
|
||||
// Create obat keluar record with status 'proses'
|
||||
ObatKeluar::create([
|
||||
'obat_masuk_id' => $item['obat_masuk_id'],
|
||||
'nama_obat' => $obatMasuk->nama_obat,
|
||||
'sumber_dana' => $obatMasuk->sumber_dana,
|
||||
'user_id' => auth()->id(),
|
||||
'kode_batch' => $obatMasuk->kode_batch,
|
||||
'barcode' => $obatMasuk->barcode,
|
||||
'jumlah' => $item['jumlah'],
|
||||
'tujuan_pemakaian' => 'Resep: ' . $resep->no_resep . ' - ' . $validated['nama_pasien'],
|
||||
'tanggal_pengeluaran' => $validated['tanggal_resep'],
|
||||
'tanggal_kadaluarsa' => $obatMasuk->tanggal_kadaluarsa,
|
||||
'no_pengeluaran' => $resep->no_resep,
|
||||
'nama_petugas' => auth()->user()->name,
|
||||
'nama_penerima' => $validated['nama_pasien'],
|
||||
'catatan' => 'Otomatis dari resep ' . $resep->no_resep,
|
||||
'status' => 'proses', // Changed from 'terkirim' to 'proses'
|
||||
]);
|
||||
|
||||
// Do NOT reduce stock here because status is 'proses'
|
||||
}
|
||||
});
|
||||
|
||||
return redirect()->route('resep.index')->with('success', 'Resep berhasil dibuat.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified prescription.
|
||||
*/
|
||||
public function show(Resep $resep)
|
||||
{
|
||||
$resep->load(['user', 'items.obatMasuk.satuan']);
|
||||
|
||||
// Mark as read if apoteker is viewing
|
||||
if (auth()->user()->isApoteker()) {
|
||||
$resep->markAsRead();
|
||||
}
|
||||
|
||||
return view('resep.show', compact('resep'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified prescription.
|
||||
*/
|
||||
public function edit(Resep $resep)
|
||||
{
|
||||
// Resep yang sudah selesai tidak bisa diedit
|
||||
if ($resep->status === 'selesai') {
|
||||
return redirect()->route('resep.show', $resep)
|
||||
->with('error', 'Resep dengan status selesai tidak dapat diedit.');
|
||||
}
|
||||
|
||||
$resep->load(['items']);
|
||||
|
||||
$obats = ObatMasuk::where(function ($q) {
|
||||
$q->where('stok', '>', 0)
|
||||
->where('tanggal_kadaluarsa', '>=', now());
|
||||
})
|
||||
->orWhereIn('id', $resep->items->pluck('obat_masuk_id'))
|
||||
->with('kategori', 'satuan')
|
||||
->orderBy('nama_obat')
|
||||
->get();
|
||||
|
||||
return view('resep.edit', compact('resep', 'obats'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified prescription in storage.
|
||||
*/
|
||||
public function update(Request $request, Resep $resep)
|
||||
{
|
||||
// Resep yang sudah selesai tidak bisa diubah
|
||||
if ($resep->status === 'selesai') {
|
||||
return redirect()->route('resep.show', $resep)
|
||||
->with('error', 'Resep dengan status selesai tidak dapat diedit.');
|
||||
}
|
||||
|
||||
$validated = $request->validate([
|
||||
// Data Resep
|
||||
'nama_dokter' => 'required|string|max:100',
|
||||
'no_sip' => 'nullable|string|max:50',
|
||||
'tanggal_resep' => 'required|date',
|
||||
'jenis_penjamin' => 'required|in:umum,BPJS Kes,BPJS Naker,Jamkesmas/KIS,R. Inap',
|
||||
'jenis_layanan' => 'required|in:BP,KIA,Gigi,UGD,Lainnya',
|
||||
// Data Pasien
|
||||
'no_rm' => 'nullable|string|max:50',
|
||||
'nama_pasien' => 'required|string|max:100',
|
||||
'alamat_pasien' => 'nullable|string|max:255',
|
||||
'jenis_kelamin' => 'required|in:L,P',
|
||||
'umur_pasien' => 'required|integer|min:0|max:150',
|
||||
'berat_badan' => 'required|numeric|min:0|max:500',
|
||||
'diagnosa' => 'required|string',
|
||||
'catatan' => 'nullable|string',
|
||||
'status' => 'required|in:proses,selesai,dibatalkan',
|
||||
// Daftar Obat
|
||||
'items' => 'required|array|min:1',
|
||||
'items.*.obat_masuk_id' => 'required|exists:obat_masuks,id',
|
||||
'items.*.jumlah' => 'required|integer|min:1',
|
||||
'items.*.aturan_pakai' => 'nullable|string|max:255',
|
||||
]);
|
||||
|
||||
DB::transaction(function () use ($validated, $resep) {
|
||||
// Restore old stock first (only if status was selesai, but update is not allowed for selesai)
|
||||
foreach ($resep->items as $oldItem) {
|
||||
// Delete related obat keluar
|
||||
ObatKeluar::where('no_pengeluaran', $resep->no_resep)
|
||||
->where('obat_masuk_id', $oldItem->obat_masuk_id)
|
||||
->delete();
|
||||
}
|
||||
|
||||
// Delete old items
|
||||
$resep->items()->delete();
|
||||
|
||||
// Validate new stock
|
||||
foreach ($validated['items'] as $item) {
|
||||
$obatMasuk = ObatMasuk::find($item['obat_masuk_id']);
|
||||
if ($obatMasuk->stok < $item['jumlah']) {
|
||||
throw new \Exception("Stok obat {$obatMasuk->nama_obat} tidak mencukupi. Tersedia: {$obatMasuk->stok}");
|
||||
}
|
||||
}
|
||||
|
||||
// Update resep
|
||||
$resep->update([
|
||||
'nama_dokter' => $validated['nama_dokter'],
|
||||
'no_sip' => $validated['no_sip'] ?? null,
|
||||
'jenis_penjamin' => $validated['jenis_penjamin'],
|
||||
'jenis_layanan' => $validated['jenis_layanan'],
|
||||
'no_rm' => $validated['no_rm'] ?? null,
|
||||
'nama_pasien' => $validated['nama_pasien'],
|
||||
'alamat_pasien' => $validated['alamat_pasien'] ?? null,
|
||||
'jenis_kelamin' => $validated['jenis_kelamin'],
|
||||
'umur_pasien' => $validated['umur_pasien'],
|
||||
'berat_badan' => $validated['berat_badan'],
|
||||
'tanggal_resep' => $validated['tanggal_resep'],
|
||||
'diagnosa' => $validated['diagnosa'],
|
||||
'catatan' => $validated['catatan'] ?? null,
|
||||
'status' => $validated['status'],
|
||||
]);
|
||||
|
||||
// Create new items and reduce stock
|
||||
foreach ($validated['items'] as $item) {
|
||||
$obatMasuk = ObatMasuk::find($item['obat_masuk_id']);
|
||||
|
||||
// Create resep item
|
||||
ResepItem::create([
|
||||
'resep_id' => $resep->id,
|
||||
'obat_masuk_id' => $item['obat_masuk_id'],
|
||||
'nama_obat' => $obatMasuk->nama_obat,
|
||||
'jumlah' => $item['jumlah'],
|
||||
'aturan_pakai' => $item['aturan_pakai'] ?? null,
|
||||
]);
|
||||
|
||||
// Create obat keluar record
|
||||
ObatKeluar::create([
|
||||
'obat_masuk_id' => $item['obat_masuk_id'],
|
||||
'nama_obat' => $obatMasuk->nama_obat,
|
||||
'sumber_dana' => $obatMasuk->sumber_dana,
|
||||
'user_id' => auth()->id(),
|
||||
'kode_batch' => $obatMasuk->kode_batch,
|
||||
'barcode' => $obatMasuk->barcode,
|
||||
'jumlah' => $item['jumlah'],
|
||||
'tujuan_pemakaian' => 'Resep: ' . $resep->no_resep . ' - ' . $validated['nama_pasien'],
|
||||
'tanggal_pengeluaran' => $validated['tanggal_resep'],
|
||||
'tanggal_kadaluarsa' => $obatMasuk->tanggal_kadaluarsa,
|
||||
'no_pengeluaran' => $resep->no_resep,
|
||||
'nama_petugas' => auth()->user()->name,
|
||||
'nama_penerima' => $validated['nama_pasien'],
|
||||
'catatan' => 'Otomatis dari resep ' . $resep->no_resep,
|
||||
'status' => $validated['status'] === 'selesai' ? 'selesai' : ($validated['status'] === 'dibatalkan' ? 'dibatalkan' : 'proses'),
|
||||
]);
|
||||
|
||||
// Reduce stock only if status is selesai
|
||||
if ($validated['status'] === 'selesai') {
|
||||
$obatMasuk->decrement('stok', $item['jumlah']);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return redirect()->route('resep.index')->with('success', 'Resep berhasil diperbarui.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the status of the specified prescription (by apoteker).
|
||||
*/
|
||||
public function updateStatus(Request $request, Resep $resep)
|
||||
{
|
||||
// Resep yang sudah selesai tidak bisa diubah statusnya
|
||||
if ($resep->status === 'selesai') {
|
||||
return redirect()->route('resep.index')
|
||||
->with('error', 'Status resep yang sudah selesai tidak dapat diubah.');
|
||||
}
|
||||
|
||||
$validated = $request->validate([
|
||||
'status' => 'required|in:proses,selesai,dibatalkan',
|
||||
]);
|
||||
|
||||
|
||||
DB::transaction(function () use ($validated, $resep) {
|
||||
$oldStatus = $resep->status;
|
||||
|
||||
$resep->update(['status' => $validated['status']]);
|
||||
|
||||
// Also update related obat keluar records
|
||||
ObatKeluar::where('no_pengeluaran', $resep->no_resep)
|
||||
->update(['status' => $validated['status']]);
|
||||
|
||||
// If changing to 'selesai', reduce stock
|
||||
if ($oldStatus !== 'selesai' && $validated['status'] === 'selesai') {
|
||||
foreach ($resep->items as $item) {
|
||||
if ($item->obatMasuk) {
|
||||
$item->obatMasuk->decrement('stok', $item->jumlah);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return redirect()->route('resep.index')->with('success', 'Status resep berhasil diperbarui.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified prescription from storage.
|
||||
*/
|
||||
public function destroy(Resep $resep)
|
||||
{
|
||||
DB::transaction(function () use ($resep) {
|
||||
// Restore stock for each item ONLY IF status was selesai
|
||||
if ($resep->status === 'selesai') {
|
||||
foreach ($resep->items as $item) {
|
||||
if ($item->obatMasuk) {
|
||||
$item->obatMasuk->increment('stok', $item->jumlah);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Delete related obat keluar
|
||||
ObatKeluar::where('no_pengeluaran', $resep->no_resep)->delete();
|
||||
|
||||
// Delete resep (items will cascade)
|
||||
$resep->delete();
|
||||
});
|
||||
|
||||
return redirect()->route('resep.index')->with('success', 'Resep berhasil dihapus dan stok dikembalikan.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the prescription.
|
||||
*/
|
||||
public function print(Resep $resep)
|
||||
{
|
||||
$resep->load(['user', 'items.obatMasuk.satuan']);
|
||||
return view('resep.print', compact('resep'));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Satuan;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class SatuanController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
$satuans = Satuan::orderBy('nama')->paginate(10);
|
||||
return view('satuan.index', compact('satuans'));
|
||||
}
|
||||
|
||||
public function create()
|
||||
{
|
||||
return view('satuan.create');
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'nama' => 'required|string|max:100|unique:satuans,nama',
|
||||
'keterangan' => 'nullable|string|max:255',
|
||||
]);
|
||||
|
||||
Satuan::create($validated);
|
||||
|
||||
return redirect()->route('satuan.index')->with('success', 'Satuan berhasil ditambahkan');
|
||||
}
|
||||
|
||||
public function edit(Satuan $satuan)
|
||||
{
|
||||
return view('satuan.edit', compact('satuan'));
|
||||
}
|
||||
|
||||
public function update(Request $request, Satuan $satuan)
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'nama' => 'required|string|max:100|unique:satuans,nama,' . $satuan->id,
|
||||
'keterangan' => 'nullable|string|max:255',
|
||||
]);
|
||||
|
||||
$satuan->update($validated);
|
||||
|
||||
return redirect()->route('satuan.index')->with('success', 'Satuan berhasil diperbarui');
|
||||
}
|
||||
|
||||
public function destroy(Satuan $satuan)
|
||||
{
|
||||
$satuan->delete();
|
||||
return redirect()->route('satuan.index')->with('success', 'Satuan berhasil dihapus');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Validation\Rules;
|
||||
|
||||
class UserManagementController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of users (dokter accounts).
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$query = User::where('role', '!=', 'superadmin');
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$search = $request->search;
|
||||
$query->where(function($q) use ($search) {
|
||||
$q->where('name', 'like', "%{$search}%")
|
||||
->orWhere('email', 'like', "%{$search}%")
|
||||
->orWhere('nip', 'like', "%{$search}%");
|
||||
});
|
||||
}
|
||||
|
||||
if ($request->filled('role')) {
|
||||
$query->where('role', $request->role);
|
||||
}
|
||||
|
||||
$users = $query->orderBy('name')->paginate(10);
|
||||
|
||||
return view('user-management.index', compact('users'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new user.
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
return view('user-management.create');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created user in storage.
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'name' => 'required|string|max:255',
|
||||
'email' => 'required|string|email|max:255|unique:users',
|
||||
'nip' => 'nullable|string|max:50',
|
||||
'phone' => 'nullable|string|max:20',
|
||||
'gender' => 'nullable|in:L,P',
|
||||
'role' => 'required|in:dokter,apoteker',
|
||||
'password' => ['required', 'confirmed', Rules\Password::defaults()],
|
||||
]);
|
||||
|
||||
$validated['password'] = Hash::make($validated['password']);
|
||||
|
||||
User::create($validated);
|
||||
|
||||
return redirect()->route('user-management.index')->with('success', 'Akun berhasil dibuat.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified user.
|
||||
*/
|
||||
public function edit(User $user)
|
||||
{
|
||||
if ($user->role === 'superadmin') {
|
||||
abort(403, 'Tidak dapat mengedit akun superadmin.');
|
||||
}
|
||||
|
||||
return view('user-management.edit', compact('user'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified user in storage.
|
||||
*/
|
||||
public function update(Request $request, User $user)
|
||||
{
|
||||
if ($user->role === 'superadmin') {
|
||||
abort(403, 'Tidak dapat mengedit akun superadmin.');
|
||||
}
|
||||
|
||||
$validated = $request->validate([
|
||||
'name' => 'required|string|max:255',
|
||||
'email' => 'required|string|email|max:255|unique:users,email,' . $user->id,
|
||||
'nip' => 'nullable|string|max:50',
|
||||
'phone' => 'nullable|string|max:20',
|
||||
'gender' => 'nullable|in:L,P',
|
||||
'role' => 'required|in:dokter,apoteker',
|
||||
'password' => ['nullable', 'confirmed', Rules\Password::defaults()],
|
||||
]);
|
||||
|
||||
if (!empty($validated['password'])) {
|
||||
$validated['password'] = Hash::make($validated['password']);
|
||||
} else {
|
||||
unset($validated['password']);
|
||||
}
|
||||
|
||||
$user->update($validated);
|
||||
|
||||
return redirect()->route('user-management.index')->with('success', 'Akun berhasil diperbarui.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified user from storage.
|
||||
*/
|
||||
public function destroy(User $user)
|
||||
{
|
||||
if ($user->id === auth()->id()) {
|
||||
return redirect()->route('user-management.index')
|
||||
->with('error', 'Tidak dapat menghapus akun sendiri.');
|
||||
}
|
||||
|
||||
if ($user->role === 'superadmin') {
|
||||
abort(403, 'Tidak dapat menghapus akun superadmin.');
|
||||
}
|
||||
|
||||
$user->delete();
|
||||
|
||||
return redirect()->route('user-management.index')->with('success', 'Akun berhasil dihapus.');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class CheckRole
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
|
||||
* @param string ...$roles
|
||||
*/
|
||||
public function handle(Request $request, Closure $next, string ...$roles): Response
|
||||
{
|
||||
if (!$request->user()) {
|
||||
return redirect()->route('login');
|
||||
}
|
||||
|
||||
$userRole = $request->user()->role;
|
||||
|
||||
// Handle comma-separated roles (e.g., 'dokter,apoteker')
|
||||
$allowedRoles = [];
|
||||
foreach ($roles as $role) {
|
||||
$allowedRoles = array_merge($allowedRoles, explode(',', $role));
|
||||
}
|
||||
|
||||
if (!in_array($userRole, $allowedRoles)) {
|
||||
abort(403, 'Anda tidak memiliki akses ke halaman ini.');
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Auth;
|
||||
|
||||
use Illuminate\Auth\Events\Lockout;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\RateLimiter;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class LoginRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
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 [
|
||||
'email' => ['required', 'string', 'email'],
|
||||
'password' => ['required', 'string'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to authenticate the request's credentials.
|
||||
*
|
||||
* @throws \Illuminate\Validation\ValidationException
|
||||
*/
|
||||
public function authenticate(): void
|
||||
{
|
||||
$this->ensureIsNotRateLimited();
|
||||
|
||||
if (! Auth::attempt($this->only('email', 'password'), $this->boolean('remember'))) {
|
||||
RateLimiter::hit($this->throttleKey());
|
||||
|
||||
throw ValidationException::withMessages([
|
||||
'email' => trans('auth.failed'),
|
||||
]);
|
||||
}
|
||||
|
||||
RateLimiter::clear($this->throttleKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the login request is not rate limited.
|
||||
*
|
||||
* @throws \Illuminate\Validation\ValidationException
|
||||
*/
|
||||
public function ensureIsNotRateLimited(): void
|
||||
{
|
||||
if (! RateLimiter::tooManyAttempts($this->throttleKey(), 5)) {
|
||||
return;
|
||||
}
|
||||
|
||||
event(new Lockout($this));
|
||||
|
||||
$seconds = RateLimiter::availableIn($this->throttleKey());
|
||||
|
||||
throw ValidationException::withMessages([
|
||||
'email' => trans('auth.throttle', [
|
||||
'seconds' => $seconds,
|
||||
'minutes' => ceil($seconds / 60),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the rate limiting throttle key for the request.
|
||||
*/
|
||||
public function throttleKey(): string
|
||||
{
|
||||
return Str::transliterate(Str::lower($this->string('email')).'|'.$this->ip());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class ProfileUpdateRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
'nip' => ['required', 'string', 'max:50'],
|
||||
'email' => [
|
||||
'required',
|
||||
'string',
|
||||
'lowercase',
|
||||
'email',
|
||||
'max:255',
|
||||
Rule::unique(User::class)->ignore($this->user()->id),
|
||||
],
|
||||
'phone' => ['required', 'string', 'max:20'],
|
||||
'gender' => ['required', 'in:laki-laki,perempuan'],
|
||||
'address' => ['nullable', 'string', 'max:1000'],
|
||||
'division' => ['required', 'string', 'max:255'],
|
||||
'position' => ['nullable', 'string', 'max:255'],
|
||||
'profile_photo' => ['nullable', 'image', 'max:2048'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
class Kategori extends Model
|
||||
{
|
||||
protected $fillable = ['nama', 'keterangan'];
|
||||
|
||||
public function obats(): HasMany
|
||||
{
|
||||
return $this->hasMany(Obat::class);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
class Obat extends Model
|
||||
{
|
||||
protected $fillable = ['kategori_id', 'nama', 'kode', 'satuan', 'deskripsi'];
|
||||
|
||||
public function kategori(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Kategori::class);
|
||||
}
|
||||
|
||||
public function obatMasuks(): HasMany
|
||||
{
|
||||
return $this->hasMany(ObatMasuk::class);
|
||||
}
|
||||
|
||||
public function obatKeluars(): HasMany
|
||||
{
|
||||
return $this->hasMany(ObatKeluar::class);
|
||||
}
|
||||
|
||||
public function getTotalStokAttribute(): int
|
||||
{
|
||||
$masuk = $this->obatMasuks()->sum('stok');
|
||||
$keluar = $this->obatKeluars()->where('status', 'terkirim')->sum('jumlah');
|
||||
return $masuk - $keluar;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class ObatKeluar extends Model
|
||||
{
|
||||
protected $fillable = [
|
||||
'obat_masuk_id',
|
||||
'nama_obat',
|
||||
'sumber_dana',
|
||||
'user_id',
|
||||
'kode_batch',
|
||||
'barcode',
|
||||
'jumlah',
|
||||
'harga',
|
||||
'harga_total',
|
||||
'tujuan_pemakaian',
|
||||
'tanggal_pengeluaran',
|
||||
'tanggal_kadaluarsa',
|
||||
'no_pengeluaran',
|
||||
'nama_petugas',
|
||||
'nama_penerima',
|
||||
'catatan',
|
||||
'status',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'tanggal_pengeluaran' => 'date',
|
||||
'tanggal_kadaluarsa' => 'date',
|
||||
'harga' => 'decimal:2',
|
||||
'harga_total' => 'decimal:2',
|
||||
];
|
||||
|
||||
public function obatMasuk(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(ObatMasuk::class);
|
||||
}
|
||||
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
public function getSisaHariAttribute(): int
|
||||
{
|
||||
return Carbon::now()->diffInDays($this->tanggal_kadaluarsa, false);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class ObatMasuk extends Model
|
||||
{
|
||||
protected $fillable = [
|
||||
'nama_obat',
|
||||
'kategori_id',
|
||||
'satuan_id',
|
||||
'obat_id',
|
||||
'sumber_dana',
|
||||
'user_id',
|
||||
'kode_batch',
|
||||
'barcode',
|
||||
'stok',
|
||||
'harga_beli',
|
||||
'harga_jual',
|
||||
'tanggal_penerimaan',
|
||||
'tanggal_kadaluarsa',
|
||||
'no_faktur',
|
||||
'no_sbbk',
|
||||
'catatan',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'tanggal_penerimaan' => 'date',
|
||||
'tanggal_kadaluarsa' => 'date',
|
||||
'harga_beli' => 'decimal:2',
|
||||
'harga_jual' => 'decimal:2',
|
||||
];
|
||||
|
||||
public function obat(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Obat::class);
|
||||
}
|
||||
|
||||
public function kategori(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Kategori::class);
|
||||
}
|
||||
|
||||
public function satuan(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Satuan::class);
|
||||
}
|
||||
|
||||
public function supplier(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Supplier::class);
|
||||
}
|
||||
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
public function getSisaHariAttribute(): int
|
||||
{
|
||||
return (int) Carbon::now()->diffInDays($this->tanggal_kadaluarsa, false);
|
||||
}
|
||||
|
||||
public function getStatusKadaluarsaAttribute(): string
|
||||
{
|
||||
$sisaHari = $this->sisa_hari;
|
||||
if ($sisaHari <= 30) {
|
||||
return 'kritis';
|
||||
} elseif ($sisaHari <= 60) {
|
||||
return 'waspada';
|
||||
} else {
|
||||
return 'aman';
|
||||
}
|
||||
}
|
||||
|
||||
public function getStatusStokAttribute(): string
|
||||
{
|
||||
return $this->stok > 0 ? 'tersedia' : 'habis';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class Resep extends Model
|
||||
{
|
||||
protected $fillable = [
|
||||
'no_resep',
|
||||
'user_id',
|
||||
'nama_dokter',
|
||||
'no_sip',
|
||||
'jenis_penjamin',
|
||||
'jenis_layanan',
|
||||
'nama_pasien',
|
||||
'no_rm',
|
||||
'umur_pasien',
|
||||
'berat_badan',
|
||||
'alamat_pasien',
|
||||
'jenis_kelamin',
|
||||
'tanggal_resep',
|
||||
'diagnosa',
|
||||
'catatan',
|
||||
'status',
|
||||
'is_read',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'tanggal_resep' => 'date',
|
||||
'berat_badan' => 'decimal:2',
|
||||
'is_read' => 'boolean',
|
||||
];
|
||||
|
||||
/**
|
||||
* Relasi ke User (Dokter yang membuat resep)
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias untuk dokter
|
||||
*/
|
||||
public function dokter(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'user_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Relasi ke item-item resep
|
||||
*/
|
||||
public function items(): HasMany
|
||||
{
|
||||
return $this->hasMany(ResepItem::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate nomor resep otomatis
|
||||
*/
|
||||
public static function generateNoResep(): string
|
||||
{
|
||||
$today = now()->format('Ymd');
|
||||
$lastResep = self::whereDate('created_at', today())
|
||||
->orderBy('id', 'desc')
|
||||
->first();
|
||||
|
||||
if ($lastResep) {
|
||||
$lastNumber = (int) substr($lastResep->no_resep, -4);
|
||||
$newNumber = $lastNumber + 1;
|
||||
} else {
|
||||
$newNumber = 1;
|
||||
}
|
||||
|
||||
return 'RSP-' . $today . '-' . str_pad($newNumber, 4, '0', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get status badge color
|
||||
*/
|
||||
public function getStatusColorAttribute(): string
|
||||
{
|
||||
return match($this->status) {
|
||||
'selesai' => 'terkirim',
|
||||
'proses' => 'proses',
|
||||
'dibatalkan' => 'dibatalkan',
|
||||
default => 'proses',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope for unread prescriptions
|
||||
*/
|
||||
public function scopeUnread(Builder $query): Builder
|
||||
{
|
||||
return $query->where('is_read', false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark prescription as read
|
||||
*/
|
||||
public function markAsRead(): void
|
||||
{
|
||||
if (!$this->is_read) {
|
||||
$this->update(['is_read' => true]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class ResepItem extends Model
|
||||
{
|
||||
protected $fillable = [
|
||||
'resep_id',
|
||||
'obat_masuk_id',
|
||||
'nama_obat',
|
||||
'jumlah',
|
||||
'aturan_pakai',
|
||||
];
|
||||
|
||||
/**
|
||||
* Relasi ke Resep
|
||||
*/
|
||||
public function resep(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Resep::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Relasi ke ObatMasuk
|
||||
*/
|
||||
public function obatMasuk(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(ObatMasuk::class);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Satuan extends Model
|
||||
{
|
||||
protected $fillable = ['nama', 'keterangan'];
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
class Supplier extends Model
|
||||
{
|
||||
protected $fillable = ['nama', 'alamat', 'telepon', 'email'];
|
||||
|
||||
public function obatMasuks(): HasMany
|
||||
{
|
||||
return $this->hasMany(ObatMasuk::class);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
// use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
|
||||
class User extends Authenticatable
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\UserFactory> */
|
||||
use HasFactory, Notifiable;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'nip',
|
||||
'email',
|
||||
'phone',
|
||||
'gender',
|
||||
'address',
|
||||
'division',
|
||||
'position',
|
||||
'profile_photo',
|
||||
'password',
|
||||
'role',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be hidden for serialization.
|
||||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
protected $hidden = [
|
||||
'password',
|
||||
'remember_token',
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the attributes that should be cast.
|
||||
*
|
||||
* @return array<string, string>
|
||||
*/
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'email_verified_at' => 'datetime',
|
||||
'password' => 'hashed',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user is a superadmin
|
||||
*/
|
||||
public function isSuperAdmin(): bool
|
||||
{
|
||||
return $this->role === 'superadmin';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user is a dokter
|
||||
*/
|
||||
public function isDokter(): bool
|
||||
{
|
||||
return $this->role === 'dokter';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user is an apoteker
|
||||
*/
|
||||
public function isApoteker(): bool
|
||||
{
|
||||
return $this->role === 'apoteker';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user can manage (create/edit/delete) resep
|
||||
*/
|
||||
public function canManageResep(): bool
|
||||
{
|
||||
return $this->isDokter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user's reseps (prescriptions they created)
|
||||
*/
|
||||
public function reseps(): HasMany
|
||||
{
|
||||
return $this->hasMany(Resep::class);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use App\Models\Resep;
|
||||
use Illuminate\Auth\Notifications\ResetPassword;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Support\Facades\View;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register any application services.
|
||||
*/
|
||||
public function register(): void
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap any application services.
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
// Kustomisasi Email Reset Password
|
||||
ResetPassword::toMailUsing(function (object $notifiable, string $token) {
|
||||
return (new MailMessage)
|
||||
->subject('Pemberitahuan Reset Password - MedData')
|
||||
->greeting('Halo ' . $notifiable->name . ',')
|
||||
->line('Anda menerima email ini karena kami menerima permintaan reset password untuk akun Anda.')
|
||||
->action('Reset Password Sekarang', url(route('password.reset', [
|
||||
'token' => $token,
|
||||
'email' => $notifiable->getEmailForPasswordReset(),
|
||||
], false)))
|
||||
->line('Link reset password ini akan kadaluarsa dalam ' . config('auth.passwords.'.config('auth.defaults.passwords').'.expire') . ' menit.')
|
||||
->line('Jika Anda tidak melakukan permintaan reset password, abaikan email ini.')
|
||||
->salutation('Salam hormat, Tim MedData Puskesmas');
|
||||
});
|
||||
|
||||
// Share unread resep count with sidebar for notification badge
|
||||
View::composer('components.sidebar', function ($view) {
|
||||
$unreadResepCount = 0;
|
||||
|
||||
if (auth()->check() && auth()->user()->isApoteker()) {
|
||||
// Show unread resep count only for apoteker
|
||||
$unreadResepCount = Resep::unread()->count();
|
||||
}
|
||||
|
||||
$view->with('unreadResepCount', $unreadResepCount);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
namespace App\View\Components;
|
||||
|
||||
use Illuminate\View\Component;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class AppLayout extends Component
|
||||
{
|
||||
/**
|
||||
* Get the view / contents that represents the component.
|
||||
*/
|
||||
public function render(): View
|
||||
{
|
||||
return view('layouts.app');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
namespace App\View\Components;
|
||||
|
||||
use Illuminate\View\Component;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class GuestLayout extends Component
|
||||
{
|
||||
/**
|
||||
* Get the view / contents that represents the component.
|
||||
*/
|
||||
public function render(): View
|
||||
{
|
||||
return view('layouts.guest');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
use Illuminate\Foundation\Application;
|
||||
use Symfony\Component\Console\Input\ArgvInput;
|
||||
|
||||
define('LARAVEL_START', microtime(true));
|
||||
|
||||
// Register the Composer autoloader...
|
||||
require __DIR__.'/vendor/autoload.php';
|
||||
|
||||
// Bootstrap Laravel and handle the command...
|
||||
/** @var Application $app */
|
||||
$app = require_once __DIR__.'/bootstrap/app.php';
|
||||
|
||||
$status = $app->handleCommand(new ArgvInput);
|
||||
|
||||
exit($status);
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Foundation\Application;
|
||||
use Illuminate\Foundation\Configuration\Exceptions;
|
||||
use Illuminate\Foundation\Configuration\Middleware;
|
||||
|
||||
return Application::configure(basePath: dirname(__DIR__))
|
||||
->withRouting(
|
||||
web: __DIR__.'/../routes/web.php',
|
||||
commands: __DIR__.'/../routes/console.php',
|
||||
health: '/up',
|
||||
)
|
||||
->withMiddleware(function (Middleware $middleware): void {
|
||||
$middleware->alias([
|
||||
'role' => \App\Http\Middleware\CheckRole::class,
|
||||
]);
|
||||
})
|
||||
->withExceptions(function (Exceptions $exceptions): void {
|
||||
//
|
||||
})->create();
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
*
|
||||
!.gitignore
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
App\Providers\AppServiceProvider::class,
|
||||
];
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
{
|
||||
"$schema": "https://getcomposer.org/schema.json",
|
||||
"name": "laravel/laravel",
|
||||
"type": "project",
|
||||
"description": "The skeleton application for the Laravel framework.",
|
||||
"keywords": ["laravel", "framework"],
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^8.2",
|
||||
"barryvdh/laravel-dompdf": "^3.1",
|
||||
"laravel/framework": "^12.0",
|
||||
"laravel/tinker": "^2.10.1",
|
||||
"maatwebsite/excel": "^3.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"fakerphp/faker": "^1.23",
|
||||
"laravel/breeze": "^2.3",
|
||||
"laravel/pail": "^1.2.2",
|
||||
"laravel/pint": "^1.24",
|
||||
"laravel/sail": "^1.41",
|
||||
"mockery/mockery": "^1.6",
|
||||
"nunomaduro/collision": "^8.6",
|
||||
"phpunit/phpunit": "^11.5.3"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"App\\": "app/",
|
||||
"Database\\Factories\\": "database/factories/",
|
||||
"Database\\Seeders\\": "database/seeders/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Tests\\": "tests/"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"setup": [
|
||||
"composer install",
|
||||
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\"",
|
||||
"@php artisan key:generate",
|
||||
"@php artisan migrate --force",
|
||||
"npm install",
|
||||
"npm run build"
|
||||
],
|
||||
"dev": [
|
||||
"Composer\\Config::disableProcessTimeout",
|
||||
"npx concurrently -c \"#93c5fd,#c4b5fd,#fb7185,#fdba74\" \"php artisan serve\" \"php artisan queue:listen --tries=1\" \"php artisan pail --timeout=0\" \"npm run dev\" --names=server,queue,logs,vite --kill-others"
|
||||
],
|
||||
"test": [
|
||||
"@php artisan config:clear --ansi",
|
||||
"@php artisan test"
|
||||
],
|
||||
"post-autoload-dump": [
|
||||
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
|
||||
"@php artisan package:discover --ansi"
|
||||
],
|
||||
"post-update-cmd": [
|
||||
"@php artisan vendor:publish --tag=laravel-assets --ansi --force"
|
||||
],
|
||||
"post-root-package-install": [
|
||||
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
|
||||
],
|
||||
"post-create-project-cmd": [
|
||||
"@php artisan key:generate --ansi",
|
||||
"@php -r \"file_exists('database/database.sqlite') || touch('database/database.sqlite');\"",
|
||||
"@php artisan migrate --graceful --ansi"
|
||||
],
|
||||
"pre-package-uninstall": [
|
||||
"Illuminate\\Foundation\\ComposerScripts::prePackageUninstall"
|
||||
]
|
||||
},
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"dont-discover": []
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"optimize-autoloader": true,
|
||||
"preferred-install": "dist",
|
||||
"sort-packages": true,
|
||||
"allow-plugins": {
|
||||
"pestphp/pest-plugin": true,
|
||||
"php-http/discovery": true
|
||||
}
|
||||
},
|
||||
"minimum-stability": "stable",
|
||||
"prefer-stable": true
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,126 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This value is the name of your application, which will be used when the
|
||||
| framework needs to place the application's name in a notification or
|
||||
| other UI elements where an application name needs to be displayed.
|
||||
|
|
||||
*/
|
||||
|
||||
'name' => env('APP_NAME', 'Laravel'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Environment
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This value determines the "environment" your application is currently
|
||||
| running in. This may determine how you prefer to configure various
|
||||
| services the application utilizes. Set this in your ".env" file.
|
||||
|
|
||||
*/
|
||||
|
||||
'env' => env('APP_ENV', 'production'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Debug Mode
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When your application is in debug mode, detailed error messages with
|
||||
| stack traces will be shown on every error that occurs within your
|
||||
| application. If disabled, a simple generic error page is shown.
|
||||
|
|
||||
*/
|
||||
|
||||
'debug' => (bool) env('APP_DEBUG', false),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application URL
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This URL is used by the console to properly generate URLs when using
|
||||
| the Artisan command line tool. You should set this to the root of
|
||||
| the application so that it's available within Artisan commands.
|
||||
|
|
||||
*/
|
||||
|
||||
'url' => env('APP_URL', 'http://localhost'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Timezone
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the default timezone for your application, which
|
||||
| will be used by the PHP date and date-time functions. The timezone
|
||||
| is set to "UTC" by default as it is suitable for most use cases.
|
||||
|
|
||||
*/
|
||||
|
||||
'timezone' => 'UTC',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Locale Configuration
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The application locale determines the default locale that will be used
|
||||
| by Laravel's translation / localization methods. This option can be
|
||||
| set to any locale for which you plan to have translation strings.
|
||||
|
|
||||
*/
|
||||
|
||||
'locale' => env('APP_LOCALE', 'en'),
|
||||
|
||||
'fallback_locale' => env('APP_FALLBACK_LOCALE', 'en'),
|
||||
|
||||
'faker_locale' => env('APP_FAKER_LOCALE', 'en_US'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Encryption Key
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This key is utilized by Laravel's encryption services and should be set
|
||||
| to a random, 32 character string to ensure that all encrypted values
|
||||
| are secure. You should do this prior to deploying the application.
|
||||
|
|
||||
*/
|
||||
|
||||
'cipher' => 'AES-256-CBC',
|
||||
|
||||
'key' => env('APP_KEY'),
|
||||
|
||||
'previous_keys' => [
|
||||
...array_filter(
|
||||
explode(',', (string) env('APP_PREVIOUS_KEYS', ''))
|
||||
),
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Maintenance Mode Driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| These configuration options determine the driver used to determine and
|
||||
| manage Laravel's "maintenance mode" status. The "cache" driver will
|
||||
| allow maintenance mode to be controlled across multiple machines.
|
||||
|
|
||||
| Supported drivers: "file", "cache"
|
||||
|
|
||||
*/
|
||||
|
||||
'maintenance' => [
|
||||
'driver' => env('APP_MAINTENANCE_DRIVER', 'file'),
|
||||
'store' => env('APP_MAINTENANCE_STORE', 'database'),
|
||||
],
|
||||
|
||||
];
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Authentication Defaults
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option defines the default authentication "guard" and password
|
||||
| reset "broker" for your application. You may change these values
|
||||
| as required, but they're a perfect start for most applications.
|
||||
|
|
||||
*/
|
||||
|
||||
'defaults' => [
|
||||
'guard' => env('AUTH_GUARD', 'web'),
|
||||
'passwords' => env('AUTH_PASSWORD_BROKER', 'users'),
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Authentication Guards
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Next, you may define every authentication guard for your application.
|
||||
| Of course, a great default configuration has been defined for you
|
||||
| which utilizes session storage plus the Eloquent user provider.
|
||||
|
|
||||
| All authentication guards have a user provider, which defines how the
|
||||
| users are actually retrieved out of your database or other storage
|
||||
| system used by the application. Typically, Eloquent is utilized.
|
||||
|
|
||||
| Supported: "session"
|
||||
|
|
||||
*/
|
||||
|
||||
'guards' => [
|
||||
'web' => [
|
||||
'driver' => 'session',
|
||||
'provider' => 'users',
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| User Providers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| All authentication guards have a user provider, which defines how the
|
||||
| users are actually retrieved out of your database or other storage
|
||||
| system used by the application. Typically, Eloquent is utilized.
|
||||
|
|
||||
| If you have multiple user tables or models you may configure multiple
|
||||
| providers to represent the model / table. These providers may then
|
||||
| be assigned to any extra authentication guards you have defined.
|
||||
|
|
||||
| Supported: "database", "eloquent"
|
||||
|
|
||||
*/
|
||||
|
||||
'providers' => [
|
||||
'users' => [
|
||||
'driver' => 'eloquent',
|
||||
'model' => env('AUTH_MODEL', App\Models\User::class),
|
||||
],
|
||||
|
||||
// 'users' => [
|
||||
// 'driver' => 'database',
|
||||
// 'table' => 'users',
|
||||
// ],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Resetting Passwords
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| These configuration options specify the behavior of Laravel's password
|
||||
| reset functionality, including the table utilized for token storage
|
||||
| and the user provider that is invoked to actually retrieve users.
|
||||
|
|
||||
| The expiry time is the number of minutes that each reset token will be
|
||||
| considered valid. This security feature keeps tokens short-lived so
|
||||
| they have less time to be guessed. You may change this as needed.
|
||||
|
|
||||
| The throttle setting is the number of seconds a user must wait before
|
||||
| generating more password reset tokens. This prevents the user from
|
||||
| quickly generating a very large amount of password reset tokens.
|
||||
|
|
||||
*/
|
||||
|
||||
'passwords' => [
|
||||
'users' => [
|
||||
'provider' => 'users',
|
||||
'table' => env('AUTH_PASSWORD_RESET_TOKEN_TABLE', 'password_reset_tokens'),
|
||||
'expire' => 60,
|
||||
'throttle' => 60,
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Password Confirmation Timeout
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may define the number of seconds before a password confirmation
|
||||
| window expires and users are asked to re-enter their password via the
|
||||
| confirmation screen. By default, the timeout lasts for three hours.
|
||||
|
|
||||
*/
|
||||
|
||||
'password_timeout' => env('AUTH_PASSWORD_TIMEOUT', 10800),
|
||||
|
||||
];
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Cache Store
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default cache store that will be used by the
|
||||
| framework. This connection is utilized if another isn't explicitly
|
||||
| specified when running a cache operation inside the application.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('CACHE_STORE', 'database'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cache Stores
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may define all of the cache "stores" for your application as
|
||||
| well as their drivers. You may even define multiple stores for the
|
||||
| same cache driver to group types of items stored in your caches.
|
||||
|
|
||||
| Supported drivers: "array", "database", "file", "memcached",
|
||||
| "redis", "dynamodb", "octane",
|
||||
| "failover", "null"
|
||||
|
|
||||
*/
|
||||
|
||||
'stores' => [
|
||||
|
||||
'array' => [
|
||||
'driver' => 'array',
|
||||
'serialize' => false,
|
||||
],
|
||||
|
||||
'database' => [
|
||||
'driver' => 'database',
|
||||
'connection' => env('DB_CACHE_CONNECTION'),
|
||||
'table' => env('DB_CACHE_TABLE', 'cache'),
|
||||
'lock_connection' => env('DB_CACHE_LOCK_CONNECTION'),
|
||||
'lock_table' => env('DB_CACHE_LOCK_TABLE'),
|
||||
],
|
||||
|
||||
'file' => [
|
||||
'driver' => 'file',
|
||||
'path' => storage_path('framework/cache/data'),
|
||||
'lock_path' => storage_path('framework/cache/data'),
|
||||
],
|
||||
|
||||
'memcached' => [
|
||||
'driver' => 'memcached',
|
||||
'persistent_id' => env('MEMCACHED_PERSISTENT_ID'),
|
||||
'sasl' => [
|
||||
env('MEMCACHED_USERNAME'),
|
||||
env('MEMCACHED_PASSWORD'),
|
||||
],
|
||||
'options' => [
|
||||
// Memcached::OPT_CONNECT_TIMEOUT => 2000,
|
||||
],
|
||||
'servers' => [
|
||||
[
|
||||
'host' => env('MEMCACHED_HOST', '127.0.0.1'),
|
||||
'port' => env('MEMCACHED_PORT', 11211),
|
||||
'weight' => 100,
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
'redis' => [
|
||||
'driver' => 'redis',
|
||||
'connection' => env('REDIS_CACHE_CONNECTION', 'cache'),
|
||||
'lock_connection' => env('REDIS_CACHE_LOCK_CONNECTION', 'default'),
|
||||
],
|
||||
|
||||
'dynamodb' => [
|
||||
'driver' => 'dynamodb',
|
||||
'key' => env('AWS_ACCESS_KEY_ID'),
|
||||
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
||||
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
|
||||
'table' => env('DYNAMODB_CACHE_TABLE', 'cache'),
|
||||
'endpoint' => env('DYNAMODB_ENDPOINT'),
|
||||
],
|
||||
|
||||
'octane' => [
|
||||
'driver' => 'octane',
|
||||
],
|
||||
|
||||
'failover' => [
|
||||
'driver' => 'failover',
|
||||
'stores' => [
|
||||
'database',
|
||||
'array',
|
||||
],
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cache Key Prefix
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When utilizing the APC, database, memcached, Redis, and DynamoDB cache
|
||||
| stores, there might be other applications using the same cache. For
|
||||
| that reason, you may prefix every cache key to avoid collisions.
|
||||
|
|
||||
*/
|
||||
|
||||
'prefix' => env('CACHE_PREFIX', Str::slug((string) env('APP_NAME', 'laravel')).'-cache-'),
|
||||
|
||||
];
|
||||
|
|
@ -0,0 +1,183 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Database Connection Name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify which of the database connections below you wish
|
||||
| to use as your default connection for database operations. This is
|
||||
| the connection which will be utilized unless another connection
|
||||
| is explicitly specified when you execute a query / statement.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('DB_CONNECTION', 'sqlite'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Database Connections
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Below are all of the database connections defined for your application.
|
||||
| An example configuration is provided for each database system which
|
||||
| is supported by Laravel. You're free to add / remove connections.
|
||||
|
|
||||
*/
|
||||
|
||||
'connections' => [
|
||||
|
||||
'sqlite' => [
|
||||
'driver' => 'sqlite',
|
||||
'url' => env('DB_URL'),
|
||||
'database' => env('DB_DATABASE', database_path('database.sqlite')),
|
||||
'prefix' => '',
|
||||
'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true),
|
||||
'busy_timeout' => null,
|
||||
'journal_mode' => null,
|
||||
'synchronous' => null,
|
||||
'transaction_mode' => 'DEFERRED',
|
||||
],
|
||||
|
||||
'mysql' => [
|
||||
'driver' => 'mysql',
|
||||
'url' => env('DB_URL'),
|
||||
'host' => env('DB_HOST', '127.0.0.1'),
|
||||
'port' => env('DB_PORT', '3306'),
|
||||
'database' => env('DB_DATABASE', 'laravel'),
|
||||
'username' => env('DB_USERNAME', 'root'),
|
||||
'password' => env('DB_PASSWORD', ''),
|
||||
'unix_socket' => env('DB_SOCKET', ''),
|
||||
'charset' => env('DB_CHARSET', 'utf8mb4'),
|
||||
'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),
|
||||
'prefix' => '',
|
||||
'prefix_indexes' => true,
|
||||
'strict' => true,
|
||||
'engine' => null,
|
||||
'options' => extension_loaded('pdo_mysql') ? array_filter([
|
||||
(PHP_VERSION_ID >= 80500 ? \Pdo\Mysql::ATTR_SSL_CA : \PDO::MYSQL_ATTR_SSL_CA) => env('MYSQL_ATTR_SSL_CA'),
|
||||
]) : [],
|
||||
],
|
||||
|
||||
'mariadb' => [
|
||||
'driver' => 'mariadb',
|
||||
'url' => env('DB_URL'),
|
||||
'host' => env('DB_HOST', '127.0.0.1'),
|
||||
'port' => env('DB_PORT', '3306'),
|
||||
'database' => env('DB_DATABASE', 'laravel'),
|
||||
'username' => env('DB_USERNAME', 'root'),
|
||||
'password' => env('DB_PASSWORD', ''),
|
||||
'unix_socket' => env('DB_SOCKET', ''),
|
||||
'charset' => env('DB_CHARSET', 'utf8mb4'),
|
||||
'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),
|
||||
'prefix' => '',
|
||||
'prefix_indexes' => true,
|
||||
'strict' => true,
|
||||
'engine' => null,
|
||||
'options' => extension_loaded('pdo_mysql') ? array_filter([
|
||||
(PHP_VERSION_ID >= 80500 ? \Pdo\Mysql::ATTR_SSL_CA : \PDO::MYSQL_ATTR_SSL_CA) => env('MYSQL_ATTR_SSL_CA'),
|
||||
]) : [],
|
||||
],
|
||||
|
||||
'pgsql' => [
|
||||
'driver' => 'pgsql',
|
||||
'url' => env('DB_URL'),
|
||||
'host' => env('DB_HOST', '127.0.0.1'),
|
||||
'port' => env('DB_PORT', '5432'),
|
||||
'database' => env('DB_DATABASE', 'laravel'),
|
||||
'username' => env('DB_USERNAME', 'root'),
|
||||
'password' => env('DB_PASSWORD', ''),
|
||||
'charset' => env('DB_CHARSET', 'utf8'),
|
||||
'prefix' => '',
|
||||
'prefix_indexes' => true,
|
||||
'search_path' => 'public',
|
||||
'sslmode' => 'prefer',
|
||||
],
|
||||
|
||||
'sqlsrv' => [
|
||||
'driver' => 'sqlsrv',
|
||||
'url' => env('DB_URL'),
|
||||
'host' => env('DB_HOST', 'localhost'),
|
||||
'port' => env('DB_PORT', '1433'),
|
||||
'database' => env('DB_DATABASE', 'laravel'),
|
||||
'username' => env('DB_USERNAME', 'root'),
|
||||
'password' => env('DB_PASSWORD', ''),
|
||||
'charset' => env('DB_CHARSET', 'utf8'),
|
||||
'prefix' => '',
|
||||
'prefix_indexes' => true,
|
||||
// 'encrypt' => env('DB_ENCRYPT', 'yes'),
|
||||
// 'trust_server_certificate' => env('DB_TRUST_SERVER_CERTIFICATE', 'false'),
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Migration Repository Table
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This table keeps track of all the migrations that have already run for
|
||||
| your application. Using this information, we can determine which of
|
||||
| the migrations on disk haven't actually been run on the database.
|
||||
|
|
||||
*/
|
||||
|
||||
'migrations' => [
|
||||
'table' => 'migrations',
|
||||
'update_date_on_publish' => true,
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Redis Databases
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Redis is an open source, fast, and advanced key-value store that also
|
||||
| provides a richer body of commands than a typical key-value system
|
||||
| such as Memcached. You may define your connection settings here.
|
||||
|
|
||||
*/
|
||||
|
||||
'redis' => [
|
||||
|
||||
'client' => env('REDIS_CLIENT', 'phpredis'),
|
||||
|
||||
'options' => [
|
||||
'cluster' => env('REDIS_CLUSTER', 'redis'),
|
||||
'prefix' => env('REDIS_PREFIX', Str::slug((string) env('APP_NAME', 'laravel')).'-database-'),
|
||||
'persistent' => env('REDIS_PERSISTENT', false),
|
||||
],
|
||||
|
||||
'default' => [
|
||||
'url' => env('REDIS_URL'),
|
||||
'host' => env('REDIS_HOST', '127.0.0.1'),
|
||||
'username' => env('REDIS_USERNAME'),
|
||||
'password' => env('REDIS_PASSWORD'),
|
||||
'port' => env('REDIS_PORT', '6379'),
|
||||
'database' => env('REDIS_DB', '0'),
|
||||
'max_retries' => env('REDIS_MAX_RETRIES', 3),
|
||||
'backoff_algorithm' => env('REDIS_BACKOFF_ALGORITHM', 'decorrelated_jitter'),
|
||||
'backoff_base' => env('REDIS_BACKOFF_BASE', 100),
|
||||
'backoff_cap' => env('REDIS_BACKOFF_CAP', 1000),
|
||||
],
|
||||
|
||||
'cache' => [
|
||||
'url' => env('REDIS_URL'),
|
||||
'host' => env('REDIS_HOST', '127.0.0.1'),
|
||||
'username' => env('REDIS_USERNAME'),
|
||||
'password' => env('REDIS_PASSWORD'),
|
||||
'port' => env('REDIS_PORT', '6379'),
|
||||
'database' => env('REDIS_CACHE_DB', '1'),
|
||||
'max_retries' => env('REDIS_MAX_RETRIES', 3),
|
||||
'backoff_algorithm' => env('REDIS_BACKOFF_ALGORITHM', 'decorrelated_jitter'),
|
||||
'backoff_base' => env('REDIS_BACKOFF_BASE', 100),
|
||||
'backoff_cap' => env('REDIS_BACKOFF_CAP', 1000),
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
];
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Filesystem Disk
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the default filesystem disk that should be used
|
||||
| by the framework. The "local" disk, as well as a variety of cloud
|
||||
| based disks are available to your application for file storage.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('FILESYSTEM_DISK', 'local'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Filesystem Disks
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Below you may configure as many filesystem disks as necessary, and you
|
||||
| may even configure multiple disks for the same driver. Examples for
|
||||
| most supported storage drivers are configured here for reference.
|
||||
|
|
||||
| Supported drivers: "local", "ftp", "sftp", "s3"
|
||||
|
|
||||
*/
|
||||
|
||||
'disks' => [
|
||||
|
||||
'local' => [
|
||||
'driver' => 'local',
|
||||
'root' => storage_path('app/private'),
|
||||
'serve' => true,
|
||||
'throw' => false,
|
||||
'report' => false,
|
||||
],
|
||||
|
||||
'public' => [
|
||||
'driver' => 'local',
|
||||
'root' => storage_path('app/public'),
|
||||
'url' => env('APP_URL').'/storage',
|
||||
'visibility' => 'public',
|
||||
'throw' => false,
|
||||
'report' => false,
|
||||
],
|
||||
|
||||
's3' => [
|
||||
'driver' => 's3',
|
||||
'key' => env('AWS_ACCESS_KEY_ID'),
|
||||
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
||||
'region' => env('AWS_DEFAULT_REGION'),
|
||||
'bucket' => env('AWS_BUCKET'),
|
||||
'url' => env('AWS_URL'),
|
||||
'endpoint' => env('AWS_ENDPOINT'),
|
||||
'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
|
||||
'throw' => false,
|
||||
'report' => false,
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Symbolic Links
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure the symbolic links that will be created when the
|
||||
| `storage:link` Artisan command is executed. The array keys should be
|
||||
| the locations of the links and the values should be their targets.
|
||||
|
|
||||
*/
|
||||
|
||||
'links' => [
|
||||
public_path('storage') => storage_path('app/public'),
|
||||
],
|
||||
|
||||
];
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
<?php
|
||||
|
||||
use Monolog\Handler\NullHandler;
|
||||
use Monolog\Handler\StreamHandler;
|
||||
use Monolog\Handler\SyslogUdpHandler;
|
||||
use Monolog\Processor\PsrLogMessageProcessor;
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Log Channel
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option defines the default log channel that is utilized to write
|
||||
| messages to your logs. The value provided here should match one of
|
||||
| the channels present in the list of "channels" configured below.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('LOG_CHANNEL', 'stack'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Deprecations Log Channel
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the log channel that should be used to log warnings
|
||||
| regarding deprecated PHP and library features. This allows you to get
|
||||
| your application ready for upcoming major versions of dependencies.
|
||||
|
|
||||
*/
|
||||
|
||||
'deprecations' => [
|
||||
'channel' => env('LOG_DEPRECATIONS_CHANNEL', 'null'),
|
||||
'trace' => env('LOG_DEPRECATIONS_TRACE', false),
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Log Channels
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure the log channels for your application. Laravel
|
||||
| utilizes the Monolog PHP logging library, which includes a variety
|
||||
| of powerful log handlers and formatters that you're free to use.
|
||||
|
|
||||
| Available drivers: "single", "daily", "slack", "syslog",
|
||||
| "errorlog", "monolog", "custom", "stack"
|
||||
|
|
||||
*/
|
||||
|
||||
'channels' => [
|
||||
|
||||
'stack' => [
|
||||
'driver' => 'stack',
|
||||
'channels' => explode(',', (string) env('LOG_STACK', 'single')),
|
||||
'ignore_exceptions' => false,
|
||||
],
|
||||
|
||||
'single' => [
|
||||
'driver' => 'single',
|
||||
'path' => storage_path('logs/laravel.log'),
|
||||
'level' => env('LOG_LEVEL', 'debug'),
|
||||
'replace_placeholders' => true,
|
||||
],
|
||||
|
||||
'daily' => [
|
||||
'driver' => 'daily',
|
||||
'path' => storage_path('logs/laravel.log'),
|
||||
'level' => env('LOG_LEVEL', 'debug'),
|
||||
'days' => env('LOG_DAILY_DAYS', 14),
|
||||
'replace_placeholders' => true,
|
||||
],
|
||||
|
||||
'slack' => [
|
||||
'driver' => 'slack',
|
||||
'url' => env('LOG_SLACK_WEBHOOK_URL'),
|
||||
'username' => env('LOG_SLACK_USERNAME', 'Laravel Log'),
|
||||
'emoji' => env('LOG_SLACK_EMOJI', ':boom:'),
|
||||
'level' => env('LOG_LEVEL', 'critical'),
|
||||
'replace_placeholders' => true,
|
||||
],
|
||||
|
||||
'papertrail' => [
|
||||
'driver' => 'monolog',
|
||||
'level' => env('LOG_LEVEL', 'debug'),
|
||||
'handler' => env('LOG_PAPERTRAIL_HANDLER', SyslogUdpHandler::class),
|
||||
'handler_with' => [
|
||||
'host' => env('PAPERTRAIL_URL'),
|
||||
'port' => env('PAPERTRAIL_PORT'),
|
||||
'connectionString' => 'tls://'.env('PAPERTRAIL_URL').':'.env('PAPERTRAIL_PORT'),
|
||||
],
|
||||
'processors' => [PsrLogMessageProcessor::class],
|
||||
],
|
||||
|
||||
'stderr' => [
|
||||
'driver' => 'monolog',
|
||||
'level' => env('LOG_LEVEL', 'debug'),
|
||||
'handler' => StreamHandler::class,
|
||||
'handler_with' => [
|
||||
'stream' => 'php://stderr',
|
||||
],
|
||||
'formatter' => env('LOG_STDERR_FORMATTER'),
|
||||
'processors' => [PsrLogMessageProcessor::class],
|
||||
],
|
||||
|
||||
'syslog' => [
|
||||
'driver' => 'syslog',
|
||||
'level' => env('LOG_LEVEL', 'debug'),
|
||||
'facility' => env('LOG_SYSLOG_FACILITY', LOG_USER),
|
||||
'replace_placeholders' => true,
|
||||
],
|
||||
|
||||
'errorlog' => [
|
||||
'driver' => 'errorlog',
|
||||
'level' => env('LOG_LEVEL', 'debug'),
|
||||
'replace_placeholders' => true,
|
||||
],
|
||||
|
||||
'null' => [
|
||||
'driver' => 'monolog',
|
||||
'handler' => NullHandler::class,
|
||||
],
|
||||
|
||||
'emergency' => [
|
||||
'path' => storage_path('logs/laravel.log'),
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
];
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Mailer
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default mailer that is used to send all email
|
||||
| messages unless another mailer is explicitly specified when sending
|
||||
| the message. All additional mailers can be configured within the
|
||||
| "mailers" array. Examples of each type of mailer are provided.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('MAIL_MAILER', 'log'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Mailer Configurations
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure all of the mailers used by your application plus
|
||||
| their respective settings. Several examples have been configured for
|
||||
| you and you are free to add your own as your application requires.
|
||||
|
|
||||
| Laravel supports a variety of mail "transport" drivers that can be used
|
||||
| when delivering an email. You may specify which one you're using for
|
||||
| your mailers below. You may also add additional mailers if needed.
|
||||
|
|
||||
| Supported: "smtp", "sendmail", "mailgun", "ses", "ses-v2",
|
||||
| "postmark", "resend", "log", "array",
|
||||
| "failover", "roundrobin"
|
||||
|
|
||||
*/
|
||||
|
||||
'mailers' => [
|
||||
|
||||
'smtp' => [
|
||||
'transport' => 'smtp',
|
||||
'scheme' => env('MAIL_SCHEME'),
|
||||
'url' => env('MAIL_URL'),
|
||||
'host' => env('MAIL_HOST', '127.0.0.1'),
|
||||
'port' => env('MAIL_PORT', 2525),
|
||||
'username' => env('MAIL_USERNAME'),
|
||||
'password' => env('MAIL_PASSWORD'),
|
||||
'timeout' => null,
|
||||
'local_domain' => env('MAIL_EHLO_DOMAIN', parse_url((string) env('APP_URL', 'http://localhost'), PHP_URL_HOST)),
|
||||
],
|
||||
|
||||
'ses' => [
|
||||
'transport' => 'ses',
|
||||
],
|
||||
|
||||
'postmark' => [
|
||||
'transport' => 'postmark',
|
||||
// 'message_stream_id' => env('POSTMARK_MESSAGE_STREAM_ID'),
|
||||
// 'client' => [
|
||||
// 'timeout' => 5,
|
||||
// ],
|
||||
],
|
||||
|
||||
'resend' => [
|
||||
'transport' => 'resend',
|
||||
],
|
||||
|
||||
'sendmail' => [
|
||||
'transport' => 'sendmail',
|
||||
'path' => env('MAIL_SENDMAIL_PATH', '/usr/sbin/sendmail -bs -i'),
|
||||
],
|
||||
|
||||
'log' => [
|
||||
'transport' => 'log',
|
||||
'channel' => env('MAIL_LOG_CHANNEL'),
|
||||
],
|
||||
|
||||
'array' => [
|
||||
'transport' => 'array',
|
||||
],
|
||||
|
||||
'failover' => [
|
||||
'transport' => 'failover',
|
||||
'mailers' => [
|
||||
'smtp',
|
||||
'log',
|
||||
],
|
||||
'retry_after' => 60,
|
||||
],
|
||||
|
||||
'roundrobin' => [
|
||||
'transport' => 'roundrobin',
|
||||
'mailers' => [
|
||||
'ses',
|
||||
'postmark',
|
||||
],
|
||||
'retry_after' => 60,
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Global "From" Address
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| You may wish for all emails sent by your application to be sent from
|
||||
| the same address. Here you may specify a name and address that is
|
||||
| used globally for all emails that are sent by your application.
|
||||
|
|
||||
*/
|
||||
|
||||
'from' => [
|
||||
'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'),
|
||||
'name' => env('MAIL_FROM_NAME', 'Example'),
|
||||
],
|
||||
|
||||
];
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Queue Connection Name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Laravel's queue supports a variety of backends via a single, unified
|
||||
| API, giving you convenient access to each backend using identical
|
||||
| syntax for each. The default queue connection is defined below.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('QUEUE_CONNECTION', 'database'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Queue Connections
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure the connection options for every queue backend
|
||||
| used by your application. An example configuration is provided for
|
||||
| each backend supported by Laravel. You're also free to add more.
|
||||
|
|
||||
| Drivers: "sync", "database", "beanstalkd", "sqs", "redis",
|
||||
| "deferred", "background", "failover", "null"
|
||||
|
|
||||
*/
|
||||
|
||||
'connections' => [
|
||||
|
||||
'sync' => [
|
||||
'driver' => 'sync',
|
||||
],
|
||||
|
||||
'database' => [
|
||||
'driver' => 'database',
|
||||
'connection' => env('DB_QUEUE_CONNECTION'),
|
||||
'table' => env('DB_QUEUE_TABLE', 'jobs'),
|
||||
'queue' => env('DB_QUEUE', 'default'),
|
||||
'retry_after' => (int) env('DB_QUEUE_RETRY_AFTER', 90),
|
||||
'after_commit' => false,
|
||||
],
|
||||
|
||||
'beanstalkd' => [
|
||||
'driver' => 'beanstalkd',
|
||||
'host' => env('BEANSTALKD_QUEUE_HOST', 'localhost'),
|
||||
'queue' => env('BEANSTALKD_QUEUE', 'default'),
|
||||
'retry_after' => (int) env('BEANSTALKD_QUEUE_RETRY_AFTER', 90),
|
||||
'block_for' => 0,
|
||||
'after_commit' => false,
|
||||
],
|
||||
|
||||
'sqs' => [
|
||||
'driver' => 'sqs',
|
||||
'key' => env('AWS_ACCESS_KEY_ID'),
|
||||
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
||||
'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'),
|
||||
'queue' => env('SQS_QUEUE', 'default'),
|
||||
'suffix' => env('SQS_SUFFIX'),
|
||||
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
|
||||
'after_commit' => false,
|
||||
],
|
||||
|
||||
'redis' => [
|
||||
'driver' => 'redis',
|
||||
'connection' => env('REDIS_QUEUE_CONNECTION', 'default'),
|
||||
'queue' => env('REDIS_QUEUE', 'default'),
|
||||
'retry_after' => (int) env('REDIS_QUEUE_RETRY_AFTER', 90),
|
||||
'block_for' => null,
|
||||
'after_commit' => false,
|
||||
],
|
||||
|
||||
'deferred' => [
|
||||
'driver' => 'deferred',
|
||||
],
|
||||
|
||||
'background' => [
|
||||
'driver' => 'background',
|
||||
],
|
||||
|
||||
'failover' => [
|
||||
'driver' => 'failover',
|
||||
'connections' => [
|
||||
'database',
|
||||
'deferred',
|
||||
],
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Job Batching
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following options configure the database and table that store job
|
||||
| batching information. These options can be updated to any database
|
||||
| connection and table which has been defined by your application.
|
||||
|
|
||||
*/
|
||||
|
||||
'batching' => [
|
||||
'database' => env('DB_CONNECTION', 'sqlite'),
|
||||
'table' => 'job_batches',
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Failed Queue Jobs
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| These options configure the behavior of failed queue job logging so you
|
||||
| can control how and where failed jobs are stored. Laravel ships with
|
||||
| support for storing failed jobs in a simple file or in a database.
|
||||
|
|
||||
| Supported drivers: "database-uuids", "dynamodb", "file", "null"
|
||||
|
|
||||
*/
|
||||
|
||||
'failed' => [
|
||||
'driver' => env('QUEUE_FAILED_DRIVER', 'database-uuids'),
|
||||
'database' => env('DB_CONNECTION', 'sqlite'),
|
||||
'table' => 'failed_jobs',
|
||||
],
|
||||
|
||||
];
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Third Party Services
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This file is for storing the credentials for third party services such
|
||||
| as Mailgun, Postmark, AWS and more. This file provides the de facto
|
||||
| location for this type of information, allowing packages to have
|
||||
| a conventional file to locate the various service credentials.
|
||||
|
|
||||
*/
|
||||
|
||||
'postmark' => [
|
||||
'key' => env('POSTMARK_API_KEY'),
|
||||
],
|
||||
|
||||
'resend' => [
|
||||
'key' => env('RESEND_API_KEY'),
|
||||
],
|
||||
|
||||
'ses' => [
|
||||
'key' => env('AWS_ACCESS_KEY_ID'),
|
||||
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
||||
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
|
||||
],
|
||||
|
||||
'slack' => [
|
||||
'notifications' => [
|
||||
'bot_user_oauth_token' => env('SLACK_BOT_USER_OAUTH_TOKEN'),
|
||||
'channel' => env('SLACK_BOT_USER_DEFAULT_CHANNEL'),
|
||||
],
|
||||
],
|
||||
|
||||
];
|
||||
|
|
@ -0,0 +1,217 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Session Driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option determines the default session driver that is utilized for
|
||||
| incoming requests. Laravel supports a variety of storage options to
|
||||
| persist session data. Database storage is a great default choice.
|
||||
|
|
||||
| Supported: "file", "cookie", "database", "memcached",
|
||||
| "redis", "dynamodb", "array"
|
||||
|
|
||||
*/
|
||||
|
||||
'driver' => env('SESSION_DRIVER', 'database'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Lifetime
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the number of minutes that you wish the session
|
||||
| to be allowed to remain idle before it expires. If you want them
|
||||
| to expire immediately when the browser is closed then you may
|
||||
| indicate that via the expire_on_close configuration option.
|
||||
|
|
||||
*/
|
||||
|
||||
'lifetime' => (int) env('SESSION_LIFETIME', 120),
|
||||
|
||||
'expire_on_close' => env('SESSION_EXPIRE_ON_CLOSE', false),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Encryption
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option allows you to easily specify that all of your session data
|
||||
| should be encrypted before it's stored. All encryption is performed
|
||||
| automatically by Laravel and you may use the session like normal.
|
||||
|
|
||||
*/
|
||||
|
||||
'encrypt' => env('SESSION_ENCRYPT', false),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session File Location
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When utilizing the "file" session driver, the session files are placed
|
||||
| on disk. The default storage location is defined here; however, you
|
||||
| are free to provide another location where they should be stored.
|
||||
|
|
||||
*/
|
||||
|
||||
'files' => storage_path('framework/sessions'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Database Connection
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using the "database" or "redis" session drivers, you may specify a
|
||||
| connection that should be used to manage these sessions. This should
|
||||
| correspond to a connection in your database configuration options.
|
||||
|
|
||||
*/
|
||||
|
||||
'connection' => env('SESSION_CONNECTION'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Database Table
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using the "database" session driver, you may specify the table to
|
||||
| be used to store sessions. Of course, a sensible default is defined
|
||||
| for you; however, you're welcome to change this to another table.
|
||||
|
|
||||
*/
|
||||
|
||||
'table' => env('SESSION_TABLE', 'sessions'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Cache Store
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using one of the framework's cache driven session backends, you may
|
||||
| define the cache store which should be used to store the session data
|
||||
| between requests. This must match one of your defined cache stores.
|
||||
|
|
||||
| Affects: "dynamodb", "memcached", "redis"
|
||||
|
|
||||
*/
|
||||
|
||||
'store' => env('SESSION_STORE'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Sweeping Lottery
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Some session drivers must manually sweep their storage location to get
|
||||
| rid of old sessions from storage. Here are the chances that it will
|
||||
| happen on a given request. By default, the odds are 2 out of 100.
|
||||
|
|
||||
*/
|
||||
|
||||
'lottery' => [2, 100],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Cookie Name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may change the name of the session cookie that is created by
|
||||
| the framework. Typically, you should not need to change this value
|
||||
| since doing so does not grant a meaningful security improvement.
|
||||
|
|
||||
*/
|
||||
|
||||
'cookie' => env(
|
||||
'SESSION_COOKIE',
|
||||
Str::slug((string) env('APP_NAME', 'laravel')).'-session'
|
||||
),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Cookie Path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The session cookie path determines the path for which the cookie will
|
||||
| be regarded as available. Typically, this will be the root path of
|
||||
| your application, but you're free to change this when necessary.
|
||||
|
|
||||
*/
|
||||
|
||||
'path' => env('SESSION_PATH', '/'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Cookie Domain
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This value determines the domain and subdomains the session cookie is
|
||||
| available to. By default, the cookie will be available to the root
|
||||
| domain without subdomains. Typically, this shouldn't be changed.
|
||||
|
|
||||
*/
|
||||
|
||||
'domain' => env('SESSION_DOMAIN'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| HTTPS Only Cookies
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| By setting this option to true, session cookies will only be sent back
|
||||
| to the server if the browser has a HTTPS connection. This will keep
|
||||
| the cookie from being sent to you when it can't be done securely.
|
||||
|
|
||||
*/
|
||||
|
||||
'secure' => env('SESSION_SECURE_COOKIE'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| HTTP Access Only
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Setting this value to true will prevent JavaScript from accessing the
|
||||
| value of the cookie and the cookie will only be accessible through
|
||||
| the HTTP protocol. It's unlikely you should disable this option.
|
||||
|
|
||||
*/
|
||||
|
||||
'http_only' => env('SESSION_HTTP_ONLY', true),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Same-Site Cookies
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option determines how your cookies behave when cross-site requests
|
||||
| take place, and can be used to mitigate CSRF attacks. By default, we
|
||||
| will set this value to "lax" to permit secure cross-site requests.
|
||||
|
|
||||
| See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#samesitesamesite-value
|
||||
|
|
||||
| Supported: "lax", "strict", "none", null
|
||||
|
|
||||
*/
|
||||
|
||||
'same_site' => env('SESSION_SAME_SITE', 'lax'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Partitioned Cookies
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Setting this value to true will tie the cookie to the top-level site for
|
||||
| a cross-site context. Partitioned cookies are accepted by the browser
|
||||
| when flagged "secure" and the Same-Site attribute is set to "none".
|
||||
|
|
||||
*/
|
||||
|
||||
'partitioned' => env('SESSION_PARTITIONED_COOKIE', false),
|
||||
|
||||
];
|
||||
|
|
@ -0,0 +1 @@
|
|||
*.sqlite*
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\User>
|
||||
*/
|
||||
class UserFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* The current password being used by the factory.
|
||||
*/
|
||||
protected static ?string $password;
|
||||
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'name' => fake()->name(),
|
||||
'email' => fake()->unique()->safeEmail(),
|
||||
'email_verified_at' => now(),
|
||||
'password' => static::$password ??= Hash::make('password'),
|
||||
'remember_token' => Str::random(10),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that the model's email address should be unverified.
|
||||
*/
|
||||
public function unverified(): static
|
||||
{
|
||||
return $this->state(fn (array $attributes) => [
|
||||
'email_verified_at' => null,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('users', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name');
|
||||
$table->string('email')->unique();
|
||||
$table->timestamp('email_verified_at')->nullable();
|
||||
$table->string('password');
|
||||
$table->rememberToken();
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::create('password_reset_tokens', function (Blueprint $table) {
|
||||
$table->string('email')->primary();
|
||||
$table->string('token');
|
||||
$table->timestamp('created_at')->nullable();
|
||||
});
|
||||
|
||||
Schema::create('sessions', function (Blueprint $table) {
|
||||
$table->string('id')->primary();
|
||||
$table->foreignId('user_id')->nullable()->index();
|
||||
$table->string('ip_address', 45)->nullable();
|
||||
$table->text('user_agent')->nullable();
|
||||
$table->longText('payload');
|
||||
$table->integer('last_activity')->index();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('users');
|
||||
Schema::dropIfExists('password_reset_tokens');
|
||||
Schema::dropIfExists('sessions');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('cache', function (Blueprint $table) {
|
||||
$table->string('key')->primary();
|
||||
$table->mediumText('value');
|
||||
$table->integer('expiration');
|
||||
});
|
||||
|
||||
Schema::create('cache_locks', function (Blueprint $table) {
|
||||
$table->string('key')->primary();
|
||||
$table->string('owner');
|
||||
$table->integer('expiration');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('cache');
|
||||
Schema::dropIfExists('cache_locks');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('jobs', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('queue')->index();
|
||||
$table->longText('payload');
|
||||
$table->unsignedTinyInteger('attempts');
|
||||
$table->unsignedInteger('reserved_at')->nullable();
|
||||
$table->unsignedInteger('available_at');
|
||||
$table->unsignedInteger('created_at');
|
||||
});
|
||||
|
||||
Schema::create('job_batches', function (Blueprint $table) {
|
||||
$table->string('id')->primary();
|
||||
$table->string('name');
|
||||
$table->integer('total_jobs');
|
||||
$table->integer('pending_jobs');
|
||||
$table->integer('failed_jobs');
|
||||
$table->longText('failed_job_ids');
|
||||
$table->mediumText('options')->nullable();
|
||||
$table->integer('cancelled_at')->nullable();
|
||||
$table->integer('created_at');
|
||||
$table->integer('finished_at')->nullable();
|
||||
});
|
||||
|
||||
Schema::create('failed_jobs', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('uuid')->unique();
|
||||
$table->text('connection');
|
||||
$table->text('queue');
|
||||
$table->longText('payload');
|
||||
$table->longText('exception');
|
||||
$table->timestamp('failed_at')->useCurrent();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('jobs');
|
||||
Schema::dropIfExists('job_batches');
|
||||
Schema::dropIfExists('failed_jobs');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('kategoris', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('nama');
|
||||
$table->string('keterangan')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('kategoris');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('suppliers', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('nama');
|
||||
$table->text('alamat')->nullable();
|
||||
$table->string('telepon')->nullable();
|
||||
$table->string('email')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('suppliers');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('obats', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('kategori_id')->constrained('kategoris')->onDelete('cascade');
|
||||
$table->string('nama');
|
||||
$table->string('kode')->unique();
|
||||
$table->string('satuan');
|
||||
$table->text('deskripsi')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('obats');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('obat_masuks', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('obat_id')->constrained('obats')->onDelete('cascade');
|
||||
$table->foreignId('supplier_id')->nullable()->constrained('suppliers')->onDelete('set null');
|
||||
$table->foreignId('user_id')->constrained('users')->onDelete('cascade');
|
||||
$table->string('kode_batch');
|
||||
$table->integer('stok');
|
||||
$table->decimal('harga_beli', 12, 2);
|
||||
$table->decimal('harga_jual', 12, 2);
|
||||
$table->date('tanggal_penerimaan');
|
||||
$table->date('tanggal_kadaluarsa');
|
||||
$table->string('no_faktur')->nullable();
|
||||
$table->text('catatan')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('obat_masuks');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('obat_keluars', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('obat_id')->constrained('obats')->onDelete('cascade');
|
||||
$table->foreignId('user_id')->constrained('users')->onDelete('cascade');
|
||||
$table->string('kode_batch');
|
||||
$table->integer('jumlah');
|
||||
$table->date('tanggal_pengeluaran');
|
||||
$table->date('tanggal_kadaluarsa');
|
||||
$table->string('no_pengeluaran')->nullable();
|
||||
$table->string('nama_petugas');
|
||||
$table->string('nama_penerima');
|
||||
$table->string('tujuan')->nullable();
|
||||
$table->text('keterangan')->nullable();
|
||||
$table->enum('status', ['terkirim', 'proses', 'dibatalkan'])->default('proses');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('obat_keluars');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('satuans', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('nama');
|
||||
$table->string('keterangan')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('satuans');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('obat_masuks', function (Blueprint $table) {
|
||||
$table->string('nama_obat', 200)->after('id');
|
||||
$table->foreignId('kategori_id')->nullable()->after('nama_obat')->constrained('kategoris')->nullOnDelete();
|
||||
$table->foreignId('satuan_id')->nullable()->after('kategori_id')->constrained('satuans')->nullOnDelete();
|
||||
|
||||
// Make obat_id nullable as we're using direct input now
|
||||
$table->foreignId('obat_id')->nullable()->change();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('obat_masuks', function (Blueprint $table) {
|
||||
$table->dropForeign(['kategori_id']);
|
||||
$table->dropForeign(['satuan_id']);
|
||||
$table->dropColumn(['nama_obat', 'kategori_id', 'satuan_id']);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('obat_masuks', function (Blueprint $table) {
|
||||
$table->string('nama_supplier')->nullable()->after('satuan_id');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('obat_masuks', function (Blueprint $table) {
|
||||
$table->dropColumn('nama_supplier');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('obat_keluars', function (Blueprint $table) {
|
||||
$table->foreignId('obat_masuk_id')->nullable()->after('id')->constrained('obat_masuks')->nullOnDelete();
|
||||
$table->string('nama_obat')->nullable()->after('obat_masuk_id');
|
||||
$table->renameColumn('keterangan', 'catatan');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('obat_keluars', function (Blueprint $table) {
|
||||
$table->dropForeign(['obat_masuk_id']);
|
||||
$table->dropColumn('obat_masuk_id');
|
||||
$table->dropColumn('nama_obat');
|
||||
$table->renameColumn('catatan', 'keterangan');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('obat_keluars', function (Blueprint $table) {
|
||||
$table->string('tujuan_pemakaian')->nullable()->after('jumlah');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('obat_keluars', function (Blueprint $table) {
|
||||
$table->dropColumn('tujuan_pemakaian');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('obat_keluars', function (Blueprint $table) {
|
||||
$table->unsignedBigInteger('obat_id')->nullable()->change();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('obat_keluars', function (Blueprint $table) {
|
||||
$table->unsignedBigInteger('obat_id')->nullable(false)->change();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->enum('role', ['dokter', 'apoteker'])->default('apoteker')->after('email');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropColumn('role');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('reseps', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('no_resep')->unique();
|
||||
$table->foreignId('user_id')->constrained()->onDelete('cascade');
|
||||
$table->string('nama_pasien');
|
||||
$table->integer('umur_pasien')->nullable();
|
||||
$table->string('alamat_pasien')->nullable();
|
||||
$table->date('tanggal_resep');
|
||||
$table->text('diagnosa')->nullable();
|
||||
$table->text('catatan')->nullable();
|
||||
$table->enum('status', ['draft', 'selesai', 'dibatalkan'])->default('selesai');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('reseps');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('resep_items', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('resep_id')->constrained()->onDelete('cascade');
|
||||
$table->foreignId('obat_masuk_id')->constrained()->onDelete('cascade');
|
||||
$table->string('nama_obat');
|
||||
$table->integer('jumlah');
|
||||
$table->string('aturan_pakai')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('resep_items');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('reseps', function (Blueprint $table) {
|
||||
// Data Resep
|
||||
$table->string('nama_dokter')->nullable()->after('user_id');
|
||||
$table->string('no_sip')->nullable()->after('nama_dokter');
|
||||
$table->enum('jenis_penjamin', ['umum', 'BPJS Kes', 'BPJS Naker', 'Jamkesmas/KIS', 'R. Inap'])->default('umum')->after('no_resep');
|
||||
$table->enum('jenis_layanan', ['BP', 'KIA', 'Gigi', 'UGD', 'Lainnya'])->default('BP')->after('jenis_penjamin');
|
||||
|
||||
// Data Pasien
|
||||
$table->string('no_rm')->nullable()->after('nama_pasien');
|
||||
$table->enum('jenis_kelamin', ['L', 'P'])->nullable()->after('alamat_pasien');
|
||||
$table->decimal('berat_badan', 5, 2)->nullable()->after('umur_pasien');
|
||||
|
||||
// Notification
|
||||
$table->boolean('is_read')->default(false)->after('status');
|
||||
});
|
||||
|
||||
// Update existing status values and change enum
|
||||
// First update any 'draft' to 'proses', then modify enum
|
||||
DB::statement("UPDATE reseps SET status = 'proses' WHERE status = 'draft'");
|
||||
|
||||
// Change enum values
|
||||
DB::statement("ALTER TABLE reseps MODIFY COLUMN status ENUM('proses', 'selesai', 'dibatalkan') DEFAULT 'proses'");
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
// Revert status enum
|
||||
DB::statement("ALTER TABLE reseps MODIFY COLUMN status ENUM('draft', 'selesai', 'dibatalkan') DEFAULT 'selesai'");
|
||||
DB::statement("UPDATE reseps SET status = 'draft' WHERE status = 'proses'");
|
||||
|
||||
Schema::table('reseps', function (Blueprint $table) {
|
||||
$table->dropColumn([
|
||||
'nama_dokter',
|
||||
'no_sip',
|
||||
'jenis_penjamin',
|
||||
'jenis_layanan',
|
||||
'no_rm',
|
||||
'jenis_kelamin',
|
||||
'berat_badan',
|
||||
'is_read',
|
||||
]);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('obat_masuks', function (Blueprint $table) {
|
||||
// Rename nama_supplier to sumber_dana
|
||||
$table->renameColumn('nama_supplier', 'sumber_dana');
|
||||
|
||||
// Add new fields
|
||||
$table->string('barcode')->nullable()->after('kode_batch');
|
||||
$table->string('no_sbbk')->nullable()->after('no_faktur');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('obat_masuks', function (Blueprint $table) {
|
||||
$table->dropColumn(['barcode', 'no_sbbk']);
|
||||
$table->renameColumn('sumber_dana', 'nama_supplier');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('obat_keluars', function (Blueprint $table) {
|
||||
// Add new fields with existence checks
|
||||
if (!Schema::hasColumn('obat_keluars', 'barcode')) {
|
||||
$table->string('barcode')->nullable()->after('kode_batch');
|
||||
}
|
||||
if (!Schema::hasColumn('obat_keluars', 'sumber_dana')) {
|
||||
$table->string('sumber_dana')->nullable()->after('tujuan_pemakaian');
|
||||
}
|
||||
if (!Schema::hasColumn('obat_keluars', 'harga')) {
|
||||
$table->decimal('harga', 15, 2)->nullable()->after('jumlah');
|
||||
}
|
||||
if (!Schema::hasColumn('obat_keluars', 'harga_total')) {
|
||||
$table->decimal('harga_total', 15, 2)->nullable()->after('harga');
|
||||
}
|
||||
});
|
||||
|
||||
// First, expand the enum to include all values (both old and new)
|
||||
DB::statement("ALTER TABLE obat_keluars MODIFY COLUMN status ENUM('terkirim', 'proses', 'selesai', 'dibatalkan') DEFAULT 'proses'");
|
||||
|
||||
// Update existing 'terkirim' status to 'selesai'
|
||||
DB::statement("UPDATE obat_keluars SET status = 'selesai' WHERE status = 'terkirim'");
|
||||
|
||||
// Finally, narrow enum to only new values
|
||||
DB::statement("ALTER TABLE obat_keluars MODIFY COLUMN status ENUM('proses', 'selesai', 'dibatalkan') DEFAULT 'proses'");
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
// Revert status enum
|
||||
DB::statement("ALTER TABLE obat_keluars MODIFY COLUMN status ENUM('terkirim', 'proses', 'dibatalkan') DEFAULT 'proses'");
|
||||
DB::statement("UPDATE obat_keluars SET status = 'terkirim' WHERE status = 'selesai'");
|
||||
|
||||
Schema::table('obat_keluars', function (Blueprint $table) {
|
||||
$table->dropColumn(['barcode', 'sumber_dana', 'harga', 'harga_total']);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('obat_masuks', function (Blueprint $table) {
|
||||
$table->decimal('harga_beli', 12, 2)->nullable()->default(0)->change();
|
||||
$table->decimal('harga_jual', 12, 2)->nullable()->default(0)->change();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('obat_masuks', function (Blueprint $table) {
|
||||
$table->decimal('harga_beli', 12, 2)->nullable(false)->default(null)->change();
|
||||
$table->decimal('harga_jual', 12, 2)->nullable(false)->default(null)->change();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->string('nip')->nullable()->after('name');
|
||||
$table->string('phone')->nullable()->after('email');
|
||||
$table->string('gender')->nullable()->after('phone');
|
||||
$table->text('address')->nullable()->after('gender');
|
||||
$table->string('division')->nullable()->after('address');
|
||||
$table->string('position')->nullable()->after('division');
|
||||
$table->string('profile_photo')->nullable()->after('position');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropColumn([
|
||||
'nip',
|
||||
'phone',
|
||||
'gender',
|
||||
'address',
|
||||
'division',
|
||||
'position',
|
||||
'profile_photo',
|
||||
]);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
// Change enum to include superadmin
|
||||
DB::statement("ALTER TABLE users MODIFY COLUMN role ENUM('dokter', 'apoteker', 'superadmin') DEFAULT 'apoteker'");
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
DB::statement("ALTER TABLE users MODIFY COLUMN role ENUM('dokter', 'apoteker') DEFAULT 'apoteker'");
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,162 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
/**
|
||||
* SQLite-compatible schema untuk testing.
|
||||
* Menggabungkan semua tabel dalam satu migration.
|
||||
*/
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('users', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name');
|
||||
$table->string('nip')->nullable();
|
||||
$table->string('email')->unique();
|
||||
$table->timestamp('email_verified_at')->nullable();
|
||||
$table->string('password');
|
||||
$table->string('phone')->nullable();
|
||||
$table->string('gender')->nullable();
|
||||
$table->string('address')->nullable();
|
||||
$table->string('division')->nullable();
|
||||
$table->string('position')->nullable();
|
||||
$table->string('profile_photo')->nullable();
|
||||
$table->string('role')->nullable()->default(null);
|
||||
$table->rememberToken();
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::create('password_reset_tokens', function (Blueprint $table) {
|
||||
$table->string('email')->primary();
|
||||
$table->string('token');
|
||||
$table->timestamp('created_at')->nullable();
|
||||
});
|
||||
|
||||
Schema::create('kategoris', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('nama')->unique();
|
||||
$table->string('keterangan')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::create('suppliers', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('nama');
|
||||
$table->string('alamat')->nullable();
|
||||
$table->string('telepon')->nullable();
|
||||
$table->string('email')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::create('satuans', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('nama')->unique();
|
||||
$table->string('keterangan')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::create('obats', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('nama');
|
||||
$table->foreignId('kategori_id')->nullable()->constrained('kategoris')->onDelete('set null');
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::create('obat_masuks', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('obat_id')->nullable()->constrained('obats')->onDelete('cascade');
|
||||
$table->foreignId('kategori_id')->nullable()->constrained('kategoris')->onDelete('set null');
|
||||
$table->foreignId('satuan_id')->nullable()->constrained('satuans')->onDelete('set null');
|
||||
$table->foreignId('supplier_id')->nullable()->constrained('suppliers')->onDelete('set null');
|
||||
$table->foreignId('user_id')->nullable()->constrained('users')->onDelete('set null');
|
||||
$table->string('nama_obat')->nullable();
|
||||
$table->string('kode_batch');
|
||||
$table->string('barcode')->nullable();
|
||||
$table->integer('stok')->default(0);
|
||||
$table->decimal('harga_beli', 12, 2)->nullable();
|
||||
$table->decimal('harga_jual', 12, 2)->nullable();
|
||||
$table->string('sumber_dana')->nullable();
|
||||
$table->string('no_sbbk')->nullable();
|
||||
$table->date('tanggal_penerimaan');
|
||||
$table->date('tanggal_kadaluarsa');
|
||||
$table->string('no_faktur')->nullable();
|
||||
$table->string('nama_supplier')->nullable();
|
||||
$table->text('catatan')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::create('obat_keluars', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('obat_masuk_id')->nullable()->constrained('obat_masuks')->onDelete('set null');
|
||||
$table->foreignId('user_id')->nullable()->constrained('users')->onDelete('set null');
|
||||
$table->string('nama_obat')->nullable();
|
||||
$table->string('kode_batch')->nullable();
|
||||
$table->string('barcode')->nullable();
|
||||
$table->integer('jumlah');
|
||||
$table->decimal('harga', 15, 2)->nullable();
|
||||
$table->decimal('harga_total', 15, 2)->nullable();
|
||||
$table->string('tujuan_pemakaian')->nullable();
|
||||
$table->string('sumber_dana')->nullable();
|
||||
$table->date('tanggal_pengeluaran');
|
||||
$table->date('tanggal_kadaluarsa')->nullable();
|
||||
$table->string('no_pengeluaran')->nullable();
|
||||
$table->string('nama_petugas')->nullable();
|
||||
$table->string('nama_penerima')->nullable();
|
||||
$table->text('catatan')->nullable();
|
||||
// SQLite tidak support ENUM, gunakan string
|
||||
$table->string('status')->default('proses');
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::create('reseps', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('no_resep')->unique();
|
||||
$table->foreignId('user_id')->nullable()->constrained('users')->onDelete('set null');
|
||||
$table->string('nama_dokter')->nullable();
|
||||
$table->string('no_sip')->nullable();
|
||||
$table->string('jenis_penjamin')->default('umum');
|
||||
$table->string('jenis_layanan')->default('BP');
|
||||
$table->string('nama_pasien');
|
||||
$table->string('no_rm')->nullable();
|
||||
$table->integer('umur_pasien')->nullable();
|
||||
$table->decimal('berat_badan', 5, 2)->nullable();
|
||||
$table->string('alamat_pasien')->nullable();
|
||||
$table->string('jenis_kelamin')->nullable();
|
||||
$table->date('tanggal_resep');
|
||||
$table->text('diagnosa')->nullable();
|
||||
$table->text('catatan')->nullable();
|
||||
// SQLite tidak support ENUM, gunakan string
|
||||
$table->string('status')->default('proses');
|
||||
$table->boolean('is_read')->default(false);
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
Schema::create('resep_items', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('resep_id')->constrained('reseps')->onDelete('cascade');
|
||||
$table->foreignId('obat_masuk_id')->nullable()->constrained('obat_masuks')->onDelete('set null');
|
||||
$table->string('nama_obat')->nullable();
|
||||
$table->integer('jumlah');
|
||||
$table->string('aturan_pakai')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('resep_items');
|
||||
Schema::dropIfExists('reseps');
|
||||
Schema::dropIfExists('obat_keluars');
|
||||
Schema::dropIfExists('obat_masuks');
|
||||
Schema::dropIfExists('obats');
|
||||
Schema::dropIfExists('satuans');
|
||||
Schema::dropIfExists('suppliers');
|
||||
Schema::dropIfExists('kategoris');
|
||||
Schema::dropIfExists('password_reset_tokens');
|
||||
Schema::dropIfExists('users');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\Kategori;
|
||||
use App\Models\Satuan;
|
||||
use App\Models\Supplier;
|
||||
use App\Models\Obat;
|
||||
use App\Models\ObatMasuk;
|
||||
use App\Models\ObatKeluar;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class DatabaseSeeder extends Seeder
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
// Create superadmin user
|
||||
$this->call([
|
||||
SuperAdminSeeder::class,
|
||||
]);
|
||||
|
||||
// Create admin user (apoteker)
|
||||
$user = User::create([
|
||||
'name' => 'Admin',
|
||||
'email' => 'admin@admin.com',
|
||||
'password' => Hash::make('password'),
|
||||
'role' => 'apoteker',
|
||||
]);
|
||||
|
||||
// Create dokter user
|
||||
User::create([
|
||||
'name' => 'Dokter',
|
||||
'email' => 'dokter@admin.com',
|
||||
'password' => Hash::make('password'),
|
||||
'role' => 'dokter',
|
||||
]);
|
||||
|
||||
// Create categories
|
||||
$kategoris = [
|
||||
['nama' => 'Analgesik', 'keterangan' => 'Obat pereda nyeri'],
|
||||
['nama' => 'Antibiotik', 'keterangan' => 'Obat anti bakteri'],
|
||||
['nama' => 'Antipiretik', 'keterangan' => 'Obat penurun demam'],
|
||||
['nama' => 'Antihipertensi', 'keterangan' => 'Obat tekanan darah tinggi'],
|
||||
['nama' => 'Antidiabetik', 'keterangan' => 'Obat diabetes'],
|
||||
['nama' => 'Vitamin dan Suplemen', 'keterangan' => 'Suplemen kesehatan'],
|
||||
];
|
||||
|
||||
foreach ($kategoris as $kategori) {
|
||||
Kategori::create($kategori);
|
||||
}
|
||||
|
||||
// Create satuans (units)
|
||||
$satuans = [
|
||||
['nama' => 'Tablet', 'keterangan' => 'Obat dalam bentuk tablet'],
|
||||
['nama' => 'Kapsul', 'keterangan' => 'Obat dalam bentuk kapsul'],
|
||||
['nama' => 'Botol', 'keterangan' => 'Obat cair dalam botol'],
|
||||
['nama' => 'Strip', 'keterangan' => 'Obat dalam kemasan strip'],
|
||||
['nama' => 'Box', 'keterangan' => 'Obat dalam kemasan box'],
|
||||
['nama' => 'Ampul', 'keterangan' => 'Obat injeksi dalam ampul'],
|
||||
['nama' => 'Tube', 'keterangan' => 'Obat salep/krim dalam tube'],
|
||||
];
|
||||
|
||||
foreach ($satuans as $satuan) {
|
||||
Satuan::create($satuan);
|
||||
}
|
||||
|
||||
// Create suppliers
|
||||
$suppliers = [
|
||||
['nama' => 'PT Kimia Farma', 'alamat' => 'Jakarta Pusat', 'telepon' => '021-1234567'],
|
||||
['nama' => 'PT Kalbe Farma', 'alamat' => 'Jakarta Timur', 'telepon' => '021-7654321'],
|
||||
['nama' => 'PT Sanbe Farma', 'alamat' => 'Bandung', 'telepon' => '022-1234567'],
|
||||
];
|
||||
|
||||
foreach ($suppliers as $supplier) {
|
||||
Supplier::create($supplier);
|
||||
}
|
||||
|
||||
// Create medicines (legacy - keep for reference)
|
||||
$obats = [
|
||||
['kategori_id' => 1, 'nama' => 'Paracetamol 500mg', 'kode' => 'OBT-001', 'satuan' => 'Tablet'],
|
||||
['kategori_id' => 1, 'nama' => 'Ibuprofen 400mg', 'kode' => 'OBT-002', 'satuan' => 'Tablet'],
|
||||
['kategori_id' => 2, 'nama' => 'Amoxicillin 500mg', 'kode' => 'OBT-003', 'satuan' => 'Kapsul'],
|
||||
['kategori_id' => 2, 'nama' => 'Ciprofloxacin 500mg', 'kode' => 'OBT-004', 'satuan' => 'Tablet'],
|
||||
['kategori_id' => 3, 'nama' => 'Aspirin 100mg', 'kode' => 'OBT-005', 'satuan' => 'Tablet'],
|
||||
['kategori_id' => 4, 'nama' => 'Amlodipine 5mg', 'kode' => 'OBT-006', 'satuan' => 'Tablet'],
|
||||
['kategori_id' => 4, 'nama' => 'Captopril 25mg', 'kode' => 'OBT-007', 'satuan' => 'Tablet'],
|
||||
['kategori_id' => 5, 'nama' => 'Metformin 500mg', 'kode' => 'OBT-008', 'satuan' => 'Tablet'],
|
||||
['kategori_id' => 6, 'nama' => 'Vitamin C 1000mg', 'kode' => 'OBT-009', 'satuan' => 'Tablet'],
|
||||
['kategori_id' => 6, 'nama' => 'Vitamin D3 1000IU', 'kode' => 'OBT-010', 'satuan' => 'Kapsul'],
|
||||
];
|
||||
|
||||
foreach ($obats as $obat) {
|
||||
Obat::create($obat);
|
||||
}
|
||||
|
||||
// Create incoming medicines with new structure
|
||||
$obatMasuks = [
|
||||
['nama_obat' => 'Paracetamol 500mg', 'kategori_id' => 1, 'satuan_id' => 1, 'obat_id' => 1, 'supplier_id' => 1, 'user_id' => 1, 'kode_batch' => 'BCH-2024-001', 'stok' => 100, 'harga_beli' => 1500, 'harga_jual' => 2500, 'tanggal_penerimaan' => Carbon::now()->subDays(30), 'tanggal_kadaluarsa' => Carbon::now()->addMonths(6), 'no_faktur' => 'FKT-001'],
|
||||
['nama_obat' => 'Ibuprofen 400mg', 'kategori_id' => 1, 'satuan_id' => 1, 'obat_id' => 2, 'supplier_id' => 1, 'user_id' => 1, 'kode_batch' => 'BCH-2024-002', 'stok' => 80, 'harga_beli' => 2000, 'harga_jual' => 3500, 'tanggal_penerimaan' => Carbon::now()->subDays(25), 'tanggal_kadaluarsa' => Carbon::now()->addDays(45), 'no_faktur' => 'FKT-002'],
|
||||
['nama_obat' => 'Amoxicillin 500mg', 'kategori_id' => 2, 'satuan_id' => 2, 'obat_id' => 3, 'supplier_id' => 2, 'user_id' => 1, 'kode_batch' => 'BCH-2024-003', 'stok' => 150, 'harga_beli' => 3000, 'harga_jual' => 5000, 'tanggal_penerimaan' => Carbon::now()->subDays(20), 'tanggal_kadaluarsa' => Carbon::now()->addMonths(12), 'no_faktur' => 'FKT-003'],
|
||||
['nama_obat' => 'Ciprofloxacin 500mg', 'kategori_id' => 2, 'satuan_id' => 1, 'obat_id' => 4, 'supplier_id' => 2, 'user_id' => 1, 'kode_batch' => 'BCH-2024-004', 'stok' => 60, 'harga_beli' => 4000, 'harga_jual' => 6500, 'tanggal_penerimaan' => Carbon::now()->subDays(15), 'tanggal_kadaluarsa' => Carbon::now()->addDays(20), 'no_faktur' => 'FKT-004'],
|
||||
['nama_obat' => 'Aspirin 100mg', 'kategori_id' => 3, 'satuan_id' => 1, 'obat_id' => 5, 'supplier_id' => 3, 'user_id' => 1, 'kode_batch' => 'BCH-2024-005', 'stok' => 200, 'harga_beli' => 1000, 'harga_jual' => 1800, 'tanggal_penerimaan' => Carbon::now()->subDays(10), 'tanggal_kadaluarsa' => Carbon::now()->addDays(75), 'no_faktur' => 'FKT-005'],
|
||||
['nama_obat' => 'Amlodipine 5mg', 'kategori_id' => 4, 'satuan_id' => 1, 'obat_id' => 6, 'supplier_id' => 1, 'user_id' => 1, 'kode_batch' => 'BCH-2024-006', 'stok' => 120, 'harga_beli' => 2500, 'harga_jual' => 4000, 'tanggal_penerimaan' => Carbon::now()->subDays(5), 'tanggal_kadaluarsa' => Carbon::now()->addMonths(8), 'no_faktur' => 'FKT-006'],
|
||||
['nama_obat' => 'Captopril 25mg', 'kategori_id' => 4, 'satuan_id' => 1, 'obat_id' => 7, 'supplier_id' => 2, 'user_id' => 1, 'kode_batch' => 'BCH-2024-007', 'stok' => 90, 'harga_beli' => 1800, 'harga_jual' => 3000, 'tanggal_penerimaan' => Carbon::now()->subDays(3), 'tanggal_kadaluarsa' => Carbon::now()->addDays(15), 'no_faktur' => 'FKT-007'],
|
||||
];
|
||||
|
||||
foreach ($obatMasuks as $obatMasuk) {
|
||||
ObatMasuk::create($obatMasuk);
|
||||
}
|
||||
|
||||
// Create outgoing medicines
|
||||
$obatKeluars = [
|
||||
['obat_id' => 1, 'user_id' => 1, 'kode_batch' => 'BCH-2024-001', 'jumlah' => 20, 'tanggal_pengeluaran' => Carbon::now()->subDays(5), 'tanggal_kadaluarsa' => Carbon::now()->addMonths(6), 'no_pengeluaran' => 'OUT-001', 'nama_petugas' => 'Admin', 'nama_penerima' => 'Apotek Sehat', 'tujuan' => 'Distribusi', 'status' => 'terkirim'],
|
||||
['obat_id' => 2, 'user_id' => 1, 'kode_batch' => 'BCH-2024-002', 'jumlah' => 15, 'tanggal_pengeluaran' => Carbon::now()->subDays(4), 'tanggal_kadaluarsa' => Carbon::now()->addDays(45), 'no_pengeluaran' => 'OUT-002', 'nama_petugas' => 'Admin', 'nama_penerima' => 'Puskesmas Maju', 'tujuan' => 'Distribusi', 'status' => 'terkirim'],
|
||||
['obat_id' => 3, 'user_id' => 1, 'kode_batch' => 'BCH-2024-003', 'jumlah' => 30, 'tanggal_pengeluaran' => Carbon::now()->subDays(3), 'tanggal_kadaluarsa' => Carbon::now()->addMonths(12), 'no_pengeluaran' => 'OUT-003', 'nama_petugas' => 'Admin', 'nama_penerima' => 'RS Harapan', 'tujuan' => 'Distribusi', 'status' => 'proses'],
|
||||
['obat_id' => 5, 'user_id' => 1, 'kode_batch' => 'BCH-2024-005', 'jumlah' => 50, 'tanggal_pengeluaran' => Carbon::now()->subDays(2), 'tanggal_kadaluarsa' => Carbon::now()->addDays(75), 'no_pengeluaran' => 'OUT-004', 'nama_petugas' => 'Admin', 'nama_penerima' => 'Klinik Pratama', 'tujuan' => 'Distribusi', 'status' => 'terkirim'],
|
||||
];
|
||||
|
||||
foreach ($obatKeluars as $obatKeluar) {
|
||||
ObatKeluar::create($obatKeluar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use App\Models\User;
|
||||
|
||||
class SuperAdminSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
User::firstOrCreate(
|
||||
['email' => 'superadmin@meddata.com'],
|
||||
[
|
||||
'name' => 'Super Admin',
|
||||
'password' => Hash::make('password'),
|
||||
'role' => 'superadmin',
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,732 @@
|
|||
-- phpMyAdmin SQL Dump
|
||||
-- version 5.2.2
|
||||
-- https://www.phpmyadmin.net/
|
||||
--
|
||||
-- Host: localhost:3306
|
||||
-- Waktu pembuatan: 24 Feb 2026 pada 11.00
|
||||
-- Versi server: 10.6.25-MariaDB
|
||||
-- Versi PHP: 8.4.16
|
||||
|
||||
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
|
||||
START TRANSACTION;
|
||||
SET time_zone = "+00:00";
|
||||
|
||||
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
||||
/*!40101 SET NAMES utf8mb4 */;
|
||||
|
||||
--
|
||||
-- Database: `medorymy_main`
|
||||
--
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktur dari tabel `cache`
|
||||
--
|
||||
|
||||
CREATE TABLE `cache` (
|
||||
`key` varchar(255) NOT NULL,
|
||||
`value` mediumtext NOT NULL,
|
||||
`expiration` int(11) NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktur dari tabel `cache_locks`
|
||||
--
|
||||
|
||||
CREATE TABLE `cache_locks` (
|
||||
`key` varchar(255) NOT NULL,
|
||||
`owner` varchar(255) NOT NULL,
|
||||
`expiration` int(11) NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktur dari tabel `failed_jobs`
|
||||
--
|
||||
|
||||
CREATE TABLE `failed_jobs` (
|
||||
`id` bigint(20) UNSIGNED NOT NULL,
|
||||
`uuid` varchar(255) NOT NULL,
|
||||
`connection` text NOT NULL,
|
||||
`queue` text NOT NULL,
|
||||
`payload` longtext NOT NULL,
|
||||
`exception` longtext NOT NULL,
|
||||
`failed_at` timestamp NOT NULL DEFAULT current_timestamp()
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktur dari tabel `jobs`
|
||||
--
|
||||
|
||||
CREATE TABLE `jobs` (
|
||||
`id` bigint(20) UNSIGNED NOT NULL,
|
||||
`queue` varchar(255) NOT NULL,
|
||||
`payload` longtext NOT NULL,
|
||||
`attempts` tinyint(3) UNSIGNED NOT NULL,
|
||||
`reserved_at` int(10) UNSIGNED DEFAULT NULL,
|
||||
`available_at` int(10) UNSIGNED NOT NULL,
|
||||
`created_at` int(10) UNSIGNED NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktur dari tabel `job_batches`
|
||||
--
|
||||
|
||||
CREATE TABLE `job_batches` (
|
||||
`id` varchar(255) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`total_jobs` int(11) NOT NULL,
|
||||
`pending_jobs` int(11) NOT NULL,
|
||||
`failed_jobs` int(11) NOT NULL,
|
||||
`failed_job_ids` longtext NOT NULL,
|
||||
`options` mediumtext DEFAULT NULL,
|
||||
`cancelled_at` int(11) DEFAULT NULL,
|
||||
`created_at` int(11) NOT NULL,
|
||||
`finished_at` int(11) DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktur dari tabel `kategoris`
|
||||
--
|
||||
|
||||
CREATE TABLE `kategoris` (
|
||||
`id` bigint(20) UNSIGNED NOT NULL,
|
||||
`nama` varchar(255) NOT NULL,
|
||||
`keterangan` varchar(255) DEFAULT NULL,
|
||||
`created_at` timestamp NULL DEFAULT NULL,
|
||||
`updated_at` timestamp NULL DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Dumping data untuk tabel `kategoris`
|
||||
--
|
||||
|
||||
INSERT INTO `kategoris` (`id`, `nama`, `keterangan`, `created_at`, `updated_at`) VALUES
|
||||
(1, 'Analgesik', 'Obat pereda nyeri', '2025-12-24 04:52:26', '2025-12-24 04:52:26'),
|
||||
(2, 'Antibiotik', 'Obat anti bakteri', '2025-12-24 04:52:26', '2025-12-24 04:52:26'),
|
||||
(3, 'Antipiretik', 'Obat penurun demam', '2025-12-24 04:52:26', '2025-12-24 04:52:26'),
|
||||
(4, 'Antihipertensi', 'Obat tekanan darah tinggi', '2025-12-24 04:52:26', '2025-12-24 04:52:26'),
|
||||
(5, 'Antidiabetik', 'Obat diabetes', '2025-12-24 04:52:26', '2025-12-24 04:52:26'),
|
||||
(6, 'Vitamin dan Suplemen', 'Suplemen kesehatan', '2025-12-24 04:52:26', '2025-12-24 04:52:26');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktur dari tabel `migrations`
|
||||
--
|
||||
|
||||
CREATE TABLE `migrations` (
|
||||
`id` int(10) UNSIGNED NOT NULL,
|
||||
`migration` varchar(255) NOT NULL,
|
||||
`batch` int(11) NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Dumping data untuk tabel `migrations`
|
||||
--
|
||||
|
||||
INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES
|
||||
(1, '0001_01_01_000000_create_users_table', 1),
|
||||
(2, '0001_01_01_000001_create_cache_table', 1),
|
||||
(3, '0001_01_01_000002_create_jobs_table', 1),
|
||||
(4, '2024_01_01_000003_create_kategoris_table', 1),
|
||||
(5, '2024_01_01_000004_create_suppliers_table', 1),
|
||||
(6, '2024_01_01_000005_create_obats_table', 1),
|
||||
(7, '2024_01_01_000006_create_obat_masuks_table', 1),
|
||||
(8, '2024_01_01_000007_create_obat_keluars_table', 1),
|
||||
(9, '2024_01_01_000008_create_satuans_table', 1),
|
||||
(10, '2024_01_01_000009_add_fields_to_obat_masuks_table', 1),
|
||||
(11, '2025_12_20_151320_add_nama_supplier_to_obat_masuks_table', 1),
|
||||
(12, '2025_12_20_152837_update_obat_keluars_use_obat_masuk', 1),
|
||||
(13, '2025_12_20_154137_add_tujuan_pemakaian_to_obat_keluars_table', 1),
|
||||
(14, '2025_12_20_155815_make_obat_id_nullable_on_obat_keluars', 1),
|
||||
(15, '2026_02_01_000001_add_role_to_users_table', 2),
|
||||
(16, '2026_02_01_000002_create_reseps_table', 3),
|
||||
(17, '2026_02_01_000003_create_resep_items_table', 4),
|
||||
(18, '2026_02_08_000001_update_reseps_table', 5),
|
||||
(19, '2026_02_08_000002_update_obat_masuks_table', 6),
|
||||
(20, '2026_02_08_000003_update_obat_keluars_table', 7),
|
||||
(21, '2026_02_10_104449_make_harga_beli_nullable_in_obat_masuks_table', 8),
|
||||
(22, '2026_02_21_000004_add_profile_fields_to_users_table', 9);
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktur dari tabel `obats`
|
||||
--
|
||||
|
||||
CREATE TABLE `obats` (
|
||||
`id` bigint(20) UNSIGNED NOT NULL,
|
||||
`kategori_id` bigint(20) UNSIGNED NOT NULL,
|
||||
`nama` varchar(255) NOT NULL,
|
||||
`kode` varchar(255) NOT NULL,
|
||||
`satuan` varchar(255) NOT NULL,
|
||||
`deskripsi` text DEFAULT NULL,
|
||||
`created_at` timestamp NULL DEFAULT NULL,
|
||||
`updated_at` timestamp NULL DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Dumping data untuk tabel `obats`
|
||||
--
|
||||
|
||||
INSERT INTO `obats` (`id`, `kategori_id`, `nama`, `kode`, `satuan`, `deskripsi`, `created_at`, `updated_at`) VALUES
|
||||
(1, 1, 'Paracetamol 500mg', 'OBT-001', 'Tablet', NULL, '2025-12-24 04:52:26', '2025-12-24 04:52:26'),
|
||||
(2, 1, 'Ibuprofen 400mg', 'OBT-002', 'Tablet', NULL, '2025-12-24 04:52:26', '2025-12-24 04:52:26'),
|
||||
(3, 2, 'Amoxicillin 500mg', 'OBT-003', 'Kapsul', NULL, '2025-12-24 04:52:26', '2025-12-24 04:52:26'),
|
||||
(4, 2, 'Ciprofloxacin 500mg', 'OBT-004', 'Tablet', NULL, '2025-12-24 04:52:26', '2025-12-24 04:52:26'),
|
||||
(5, 3, 'Aspirin 100mg', 'OBT-005', 'Tablet', NULL, '2025-12-24 04:52:26', '2025-12-24 04:52:26'),
|
||||
(6, 4, 'Amlodipine 5mg', 'OBT-006', 'Tablet', NULL, '2025-12-24 04:52:26', '2025-12-24 04:52:26'),
|
||||
(7, 4, 'Captopril 25mg', 'OBT-007', 'Tablet', NULL, '2025-12-24 04:52:26', '2025-12-24 04:52:26'),
|
||||
(8, 5, 'Metformin 500mg', 'OBT-008', 'Tablet', NULL, '2025-12-24 04:52:26', '2025-12-24 04:52:26'),
|
||||
(9, 6, 'Vitamin C 1000mg', 'OBT-009', 'Tablet', NULL, '2025-12-24 04:52:26', '2025-12-24 04:52:26'),
|
||||
(10, 6, 'Vitamin D3 1000IU', 'OBT-010', 'Kapsul', NULL, '2025-12-24 04:52:26', '2025-12-24 04:52:26');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktur dari tabel `obat_keluars`
|
||||
--
|
||||
|
||||
CREATE TABLE `obat_keluars` (
|
||||
`id` bigint(20) UNSIGNED NOT NULL,
|
||||
`obat_masuk_id` bigint(20) UNSIGNED DEFAULT NULL,
|
||||
`nama_obat` varchar(255) DEFAULT NULL,
|
||||
`obat_id` bigint(20) UNSIGNED DEFAULT NULL,
|
||||
`user_id` bigint(20) UNSIGNED NOT NULL,
|
||||
`kode_batch` varchar(255) NOT NULL,
|
||||
`barcode` varchar(255) DEFAULT NULL,
|
||||
`jumlah` int(11) NOT NULL,
|
||||
`harga` decimal(15,2) DEFAULT NULL,
|
||||
`harga_total` decimal(15,2) DEFAULT NULL,
|
||||
`tujuan_pemakaian` varchar(255) DEFAULT NULL,
|
||||
`sumber_dana` varchar(255) DEFAULT NULL,
|
||||
`tanggal_pengeluaran` date NOT NULL,
|
||||
`tanggal_kadaluarsa` date NOT NULL,
|
||||
`no_pengeluaran` varchar(255) DEFAULT NULL,
|
||||
`nama_petugas` varchar(255) NOT NULL,
|
||||
`nama_penerima` varchar(255) NOT NULL,
|
||||
`tujuan` varchar(255) DEFAULT NULL,
|
||||
`catatan` text DEFAULT NULL,
|
||||
`status` enum('proses','selesai','dibatalkan') DEFAULT 'proses',
|
||||
`created_at` timestamp NULL DEFAULT NULL,
|
||||
`updated_at` timestamp NULL DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Dumping data untuk tabel `obat_keluars`
|
||||
--
|
||||
|
||||
INSERT INTO `obat_keluars` (`id`, `obat_masuk_id`, `nama_obat`, `obat_id`, `user_id`, `kode_batch`, `barcode`, `jumlah`, `harga`, `harga_total`, `tujuan_pemakaian`, `sumber_dana`, `tanggal_pengeluaran`, `tanggal_kadaluarsa`, `no_pengeluaran`, `nama_petugas`, `nama_penerima`, `tujuan`, `catatan`, `status`, `created_at`, `updated_at`) VALUES
|
||||
(1, NULL, NULL, 1, 1, 'BCH-2024-001', NULL, 20, NULL, NULL, NULL, NULL, '2025-12-19', '2026-06-24', 'OUT-001', 'Admin', 'Apotek Sehat', 'Distribusi', NULL, 'selesai', '2025-12-24 04:52:26', '2025-12-24 04:52:26'),
|
||||
(2, NULL, NULL, 2, 1, 'BCH-2024-002', NULL, 15, NULL, NULL, NULL, NULL, '2025-12-20', '2026-02-07', 'OUT-002', 'Admin', 'Puskesmas Maju', 'Distribusi', NULL, 'selesai', '2025-12-24 04:52:26', '2025-12-24 04:52:26'),
|
||||
(3, NULL, NULL, 3, 1, 'BCH-2024-003', NULL, 30, NULL, NULL, NULL, NULL, '2025-12-21', '2026-12-24', 'OUT-003', 'Admin', 'RS Harapan', 'Distribusi', NULL, 'proses', '2025-12-24 04:52:26', '2025-12-24 04:52:26'),
|
||||
(4, NULL, NULL, 5, 1, 'BCH-2024-005', NULL, 50, NULL, NULL, NULL, NULL, '2025-12-22', '2026-03-09', 'OUT-004', 'Admin', 'Klinik Pratama', 'Distribusi', NULL, 'selesai', '2025-12-24 04:52:26', '2025-12-24 04:52:26'),
|
||||
(5, 7, 'Captopril 25mg', NULL, 1, 'BCH-2024-007', NULL, 2, NULL, NULL, 'RAWAT INAP', NULL, '2025-12-24', '2025-12-31', NULL, 'JARWO', 'siti', NULL, NULL, 'proses', '2025-12-24 05:00:17', '2025-12-24 05:00:17'),
|
||||
(6, 3, 'Amoxicillin 500mg', NULL, 2, 'BCH-2024-003', NULL, 1, NULL, NULL, 'Resep: RSP-20260202-0001 - sakina', NULL, '2026-02-02', '2026-12-24', 'RSP-20260202-0001', 'Dokter', 'sakina', NULL, 'Otomatis dari resep RSP-20260202-0001', 'selesai', '2026-02-01 20:14:12', '2026-02-10 07:15:45'),
|
||||
(7, 2, 'Ibuprofen 400mg', NULL, 2, 'BCH-2024-002', NULL, 1, NULL, NULL, 'Resep: RSP-20260203-0001 - elsa', NULL, '2026-02-03', '2026-02-07', 'RSP-20260203-0001', 'Dokter', 'elsa', NULL, 'Otomatis dari resep RSP-20260203-0001', 'selesai', '2026-02-02 20:12:25', '2026-02-02 20:12:25'),
|
||||
(8, 6, 'Amlodipine 5mg', NULL, 2, 'BCH-2024-006', NULL, 1, NULL, NULL, 'Resep: RSP-20260210-0001 - a', NULL, '2026-02-10', '2026-08-24', 'RSP-20260210-0001', 'Dokter', 'a', NULL, 'Otomatis dari resep RSP-20260210-0001', 'selesai', '2026-02-10 07:20:40', '2026-02-10 08:00:24'),
|
||||
(9, 6, 'Amlodipine 5mg', NULL, 2, 'BCH-2024-006', NULL, 1, NULL, NULL, 'Resep: RSP-20260215-0001 - Zeril', NULL, '2026-02-15', '2026-08-24', 'RSP-20260215-0001', 'Dokter', 'Zeril', NULL, 'Otomatis dari resep RSP-20260215-0001', 'selesai', '2026-02-15 08:11:11', '2026-02-15 08:11:58');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktur dari tabel `obat_masuks`
|
||||
--
|
||||
|
||||
CREATE TABLE `obat_masuks` (
|
||||
`id` bigint(20) UNSIGNED NOT NULL,
|
||||
`nama_obat` varchar(200) NOT NULL,
|
||||
`kategori_id` bigint(20) UNSIGNED DEFAULT NULL,
|
||||
`satuan_id` bigint(20) UNSIGNED DEFAULT NULL,
|
||||
`sumber_dana` varchar(255) DEFAULT NULL,
|
||||
`obat_id` bigint(20) UNSIGNED DEFAULT NULL,
|
||||
`supplier_id` bigint(20) UNSIGNED DEFAULT NULL,
|
||||
`user_id` bigint(20) UNSIGNED NOT NULL,
|
||||
`kode_batch` varchar(255) NOT NULL,
|
||||
`barcode` varchar(255) DEFAULT NULL,
|
||||
`stok` int(11) NOT NULL,
|
||||
`harga_beli` decimal(12,2) DEFAULT 0.00,
|
||||
`harga_jual` decimal(12,2) DEFAULT 0.00,
|
||||
`tanggal_penerimaan` date NOT NULL,
|
||||
`tanggal_kadaluarsa` date NOT NULL,
|
||||
`no_faktur` varchar(255) DEFAULT NULL,
|
||||
`no_sbbk` varchar(255) DEFAULT NULL,
|
||||
`catatan` text DEFAULT NULL,
|
||||
`created_at` timestamp NULL DEFAULT NULL,
|
||||
`updated_at` timestamp NULL DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Dumping data untuk tabel `obat_masuks`
|
||||
--
|
||||
|
||||
INSERT INTO `obat_masuks` (`id`, `nama_obat`, `kategori_id`, `satuan_id`, `sumber_dana`, `obat_id`, `supplier_id`, `user_id`, `kode_batch`, `barcode`, `stok`, `harga_beli`, `harga_jual`, `tanggal_penerimaan`, `tanggal_kadaluarsa`, `no_faktur`, `no_sbbk`, `catatan`, `created_at`, `updated_at`) VALUES
|
||||
(1, 'Paracetamol 500mg', 1, 1, NULL, 1, 1, 1, 'BCH-2024-001', NULL, 100, 1500.00, 2500.00, '2025-11-24', '2026-06-24', 'FKT-001', NULL, NULL, '2025-12-24 04:52:26', '2025-12-24 04:52:26'),
|
||||
(2, 'Ibuprofen 400mg', 1, 1, NULL, 2, 1, 1, 'BCH-2024-002', NULL, 79, 2000.00, 3500.00, '2025-11-29', '2026-02-07', 'FKT-002', NULL, NULL, '2025-12-24 04:52:26', '2026-02-02 20:12:25'),
|
||||
(3, 'Amoxicillin 500mg', 2, 2, NULL, 3, 2, 1, 'BCH-2024-003', NULL, 149, 3000.00, 5000.00, '2025-12-04', '2026-12-24', 'FKT-003', NULL, NULL, '2025-12-24 04:52:26', '2026-02-01 20:14:12'),
|
||||
(4, 'Ciprofloxacin 500mg', 2, 1, NULL, 4, 2, 1, 'BCH-2024-004', NULL, 60, 4000.00, 6500.00, '2025-12-09', '2026-01-13', 'FKT-004', NULL, NULL, '2025-12-24 04:52:26', '2025-12-24 04:52:26'),
|
||||
(5, 'Aspirin 100mg', 3, 1, NULL, 5, 3, 1, 'BCH-2024-005', NULL, 200, 1000.00, 1800.00, '2025-12-14', '2026-03-09', 'FKT-005', NULL, NULL, '2025-12-24 04:52:26', '2025-12-24 04:52:26'),
|
||||
(6, 'Amlodipine 5mg', 4, 1, NULL, 6, 1, 1, 'BCH-2024-006', NULL, 118, 2500.00, 4000.00, '2025-12-19', '2026-08-24', 'FKT-006', NULL, NULL, '2025-12-24 04:52:26', '2026-02-15 08:11:11'),
|
||||
(7, 'Captopril 25mg', 4, 1, NULL, 7, 2, 1, 'BCH-2024-007', NULL, 88, 1800.00, 3000.00, '2025-12-21', '2026-01-08', 'FKT-007', NULL, NULL, '2025-12-24 04:52:26', '2025-12-24 05:00:17');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktur dari tabel `password_reset_tokens`
|
||||
--
|
||||
|
||||
CREATE TABLE `password_reset_tokens` (
|
||||
`email` varchar(255) NOT NULL,
|
||||
`token` varchar(255) NOT NULL,
|
||||
`created_at` timestamp NULL DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktur dari tabel `reseps`
|
||||
--
|
||||
|
||||
CREATE TABLE `reseps` (
|
||||
`id` bigint(20) UNSIGNED NOT NULL,
|
||||
`no_resep` varchar(255) NOT NULL,
|
||||
`jenis_penjamin` enum('umum','BPJS Kes','BPJS Naker','Jamkesmas/KIS','R. Inap') NOT NULL DEFAULT 'umum',
|
||||
`jenis_layanan` enum('BP','KIA','Gigi','UGD','Lainnya') NOT NULL DEFAULT 'BP',
|
||||
`user_id` bigint(20) UNSIGNED NOT NULL,
|
||||
`nama_dokter` varchar(255) DEFAULT NULL,
|
||||
`no_sip` varchar(255) DEFAULT NULL,
|
||||
`nama_pasien` varchar(255) NOT NULL,
|
||||
`no_rm` varchar(255) DEFAULT NULL,
|
||||
`umur_pasien` int(11) DEFAULT NULL,
|
||||
`berat_badan` decimal(5,2) DEFAULT NULL,
|
||||
`alamat_pasien` varchar(255) DEFAULT NULL,
|
||||
`jenis_kelamin` enum('L','P') DEFAULT NULL,
|
||||
`tanggal_resep` date NOT NULL,
|
||||
`diagnosa` text DEFAULT NULL,
|
||||
`catatan` text DEFAULT NULL,
|
||||
`status` enum('proses','selesai','dibatalkan') DEFAULT 'proses',
|
||||
`is_read` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`created_at` timestamp NULL DEFAULT NULL,
|
||||
`updated_at` timestamp NULL DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Dumping data untuk tabel `reseps`
|
||||
--
|
||||
|
||||
INSERT INTO `reseps` (`id`, `no_resep`, `jenis_penjamin`, `jenis_layanan`, `user_id`, `nama_dokter`, `no_sip`, `nama_pasien`, `no_rm`, `umur_pasien`, `berat_badan`, `alamat_pasien`, `jenis_kelamin`, `tanggal_resep`, `diagnosa`, `catatan`, `status`, `is_read`, `created_at`, `updated_at`) VALUES
|
||||
(1, 'RSP-20260202-0001', 'umum', 'BP', 2, NULL, NULL, 'sakina', NULL, 21, NULL, 'nganjuk', NULL, '2026-02-02', 'batuk', NULL, 'selesai', 1, '2026-02-01 20:14:12', '2026-02-10 07:15:45'),
|
||||
(2, 'RSP-20260203-0001', 'umum', 'BP', 2, NULL, NULL, 'elsa', NULL, 21, NULL, 'nganjuk', NULL, '2026-02-03', 'batuk', NULL, 'selesai', 1, '2026-02-02 20:12:25', '2026-02-08 18:43:51'),
|
||||
(3, 'RSP-20260210-0001', 'umum', 'BP', 2, 'Dokter', '1', 'a', '1', 22, 22.00, 'a', 'L', '2026-02-10', 'q', NULL, 'selesai', 1, '2026-02-10 07:20:40', '2026-02-13 08:24:48'),
|
||||
(4, 'RSP-20260215-0001', 'umum', 'UGD', 2, 'Sumanto Spjp', '3121', 'Zeril', '030475', 3, 29.00, 'Jalan sumolawang', 'L', '2026-02-15', 'Cholera', 'asdasd', 'selesai', 1, '2026-02-15 08:11:11', '2026-02-15 08:11:58');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktur dari tabel `resep_items`
|
||||
--
|
||||
|
||||
CREATE TABLE `resep_items` (
|
||||
`id` bigint(20) UNSIGNED NOT NULL,
|
||||
`resep_id` bigint(20) UNSIGNED NOT NULL,
|
||||
`obat_masuk_id` bigint(20) UNSIGNED NOT NULL,
|
||||
`nama_obat` varchar(255) NOT NULL,
|
||||
`jumlah` int(11) NOT NULL,
|
||||
`aturan_pakai` varchar(255) DEFAULT NULL,
|
||||
`created_at` timestamp NULL DEFAULT NULL,
|
||||
`updated_at` timestamp NULL DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Dumping data untuk tabel `resep_items`
|
||||
--
|
||||
|
||||
INSERT INTO `resep_items` (`id`, `resep_id`, `obat_masuk_id`, `nama_obat`, `jumlah`, `aturan_pakai`, `created_at`, `updated_at`) VALUES
|
||||
(1, 1, 3, 'Amoxicillin 500mg', 1, '3x1', '2026-02-01 20:14:12', '2026-02-01 20:14:12'),
|
||||
(2, 2, 2, 'Ibuprofen 400mg', 1, '3x1', '2026-02-02 20:12:25', '2026-02-02 20:12:25'),
|
||||
(3, 3, 6, 'Amlodipine 5mg', 1, '2', '2026-02-10 07:20:40', '2026-02-10 07:20:40'),
|
||||
(4, 4, 6, 'Amlodipine 5mg', 1, '2x1 hari', '2026-02-15 08:11:11', '2026-02-15 08:11:11');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktur dari tabel `satuans`
|
||||
--
|
||||
|
||||
CREATE TABLE `satuans` (
|
||||
`id` bigint(20) UNSIGNED NOT NULL,
|
||||
`nama` varchar(255) NOT NULL,
|
||||
`keterangan` varchar(255) DEFAULT NULL,
|
||||
`created_at` timestamp NULL DEFAULT NULL,
|
||||
`updated_at` timestamp NULL DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Dumping data untuk tabel `satuans`
|
||||
--
|
||||
|
||||
INSERT INTO `satuans` (`id`, `nama`, `keterangan`, `created_at`, `updated_at`) VALUES
|
||||
(1, 'Tablet', 'Obat dalam bentuk tablet', '2025-12-24 04:52:26', '2025-12-24 04:52:26'),
|
||||
(2, 'Kapsul', 'Obat dalam bentuk kapsul', '2025-12-24 04:52:26', '2025-12-24 04:52:26'),
|
||||
(3, 'Botol', 'Obat cair dalam botol', '2025-12-24 04:52:26', '2025-12-24 04:52:26'),
|
||||
(4, 'Strip', 'Obat dalam kemasan strip', '2025-12-24 04:52:26', '2025-12-24 04:52:26'),
|
||||
(5, 'Box', 'Obat dalam kemasan box', '2025-12-24 04:52:26', '2025-12-24 04:52:26'),
|
||||
(6, 'Ampul', 'Obat injeksi dalam ampul', '2025-12-24 04:52:26', '2025-12-24 04:52:26'),
|
||||
(7, 'Tube', 'Obat salep/krim dalam tube', '2025-12-24 04:52:26', '2025-12-24 04:52:26');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktur dari tabel `sessions`
|
||||
--
|
||||
|
||||
CREATE TABLE `sessions` (
|
||||
`id` varchar(255) NOT NULL,
|
||||
`user_id` bigint(20) UNSIGNED DEFAULT NULL,
|
||||
`ip_address` varchar(45) DEFAULT NULL,
|
||||
`user_agent` text DEFAULT NULL,
|
||||
`payload` longtext NOT NULL,
|
||||
`last_activity` int(11) NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Dumping data untuk tabel `sessions`
|
||||
--
|
||||
|
||||
INSERT INTO `sessions` (`id`, `user_id`, `ip_address`, `user_agent`, `payload`, `last_activity`) VALUES
|
||||
('1g3NQU9PNE9FQ0rvC1N3ned4PHXx0sIEbrsLRxUn', NULL, '195.88.211.210', '', 'YToyOntzOjY6Il90b2tlbiI7czo0MDoidEhLbXp0ME5Jbm1scUMwWG0zMHNCbGRRanRlUXFiaWRKbHlpbTlFTSI7czo2OiJfZmxhc2giO2E6Mjp7czozOiJvbGQiO2E6MDp7fXM6MzoibmV3IjthOjA6e319fQ==', 1771901099),
|
||||
('9bKoAehhblz7fX4QRAJWTPj1TNsbxcKlJvcixar6', 1, '103.47.132.3', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36', 'YTo0OntzOjY6Il90b2tlbiI7czo0MDoieDJiOGlPR01YNEpnZzFHZFhuNHM4YUV3WFd4WGlVbklwYUtjNDJwVyI7czo2OiJfZmxhc2giO2E6Mjp7czozOiJvbGQiO2E6MDp7fXM6MzoibmV3IjthOjA6e319czo5OiJfcHJldmlvdXMiO2E6Mjp7czozOiJ1cmwiO3M6Mjc6Imh0dHA6Ly9tZWRvcnkubXkuaWQvbGFwb3JhbiI7czo1OiJyb3V0ZSI7czoxMzoibGFwb3Jhbi5pbmRleCI7fXM6NTA6ImxvZ2luX3dlYl81OWJhMzZhZGRjMmIyZjk0MDE1ODBmMDE0YzdmNThlYTRlMzA5ODlkIjtpOjE7fQ==', 1771905550),
|
||||
('g0n8avzVw75To8mj6PdeIGnazvxnzx9r54IVoK7A', 1, '114.5.109.115', 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36', 'YTo0OntzOjY6Il90b2tlbiI7czo0MDoibEh6andaYkF3NEpKb0JvVU1WMnJwVDNKN0VzN0wwUkRkaEw0aXUxMSI7czo5OiJfcHJldmlvdXMiO2E6Mjp7czozOiJ1cmwiO3M6Mjg6Imh0dHBzOi8vbWVkb3J5Lm15LmlkL3Byb2ZpbGUiO3M6NToicm91dGUiO3M6MTI6InByb2ZpbGUuZWRpdCI7fXM6NjoiX2ZsYXNoIjthOjI6e3M6Mzoib2xkIjthOjA6e31zOjM6Im5ldyI7YTowOnt9fXM6NTA6ImxvZ2luX3dlYl81OWJhMzZhZGRjMmIyZjk0MDE1ODBmMDE0YzdmNThlYTRlMzA5ODlkIjtpOjE7fQ==', 1771901915),
|
||||
('gVxifbxk3gC95ALrQNEyR7Fxm5Fb9IdL3i53oGMz', NULL, '195.88.211.210', '', 'YToyOntzOjY6Il90b2tlbiI7czo0MDoidDlxTmJyZHNSSnowaUpIbEZmMHdyZXBraUwwZlNuY2pCZmtKSzFWYiI7czo2OiJfZmxhc2giO2E6Mjp7czozOiJvbGQiO2E6MDp7fXM6MzoibmV3IjthOjA6e319fQ==', 1771903034),
|
||||
('kEUk9HMFphkzhmnZGbrlh8NkfVADsqDKZi3WFHlu', NULL, '103.22.242.5', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36', 'YTozOntzOjY6Il90b2tlbiI7czo0MDoiaXNWZE1jZjN0cmRxaW5yeGZmektkd0xKckczcDN0UU9xbVVIdlczSyI7czo5OiJfcHJldmlvdXMiO2E6Mjp7czozOiJ1cmwiO3M6MjY6Imh0dHBzOi8vbWVkb3J5Lm15LmlkL2xvZ2luIjtzOjU6InJvdXRlIjtzOjU6ImxvZ2luIjt9czo2OiJfZmxhc2giO2E6Mjp7czozOiJvbGQiO2E6MDp7fXM6MzoibmV3IjthOjA6e319fQ==', 1771904688),
|
||||
('kWxA6pifHGIShUmw171i7iaWZx83ufptkw94PZIV', NULL, '117.103.171.5', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36', 'YTo0OntzOjY6Il90b2tlbiI7czo0MDoiSEg0ZHZIWnl0MHgxc1llNFRUQmRXck5DSnRNSG1CYW5yZ1l4aDVhViI7czozOiJ1cmwiO2E6MTp7czo4OiJpbnRlbmRlZCI7czoyNjoiaHR0cHM6Ly9tZWRvcnkubXkuaWQvcmVzZXAiO31zOjk6Il9wcmV2aW91cyI7YToyOntzOjM6InVybCI7czoyNjoiaHR0cHM6Ly9tZWRvcnkubXkuaWQvbG9naW4iO3M6NToicm91dGUiO3M6NToibG9naW4iO31zOjY6Il9mbGFzaCI7YToyOntzOjM6Im9sZCI7YTowOnt9czozOiJuZXciO2E6MDp7fX19', 1771904719),
|
||||
('LzU9kxWAhGdDTbxY6ulTkB4xD6pwcyTnkEdGeeGs', NULL, '195.88.211.210', '', 'YToyOntzOjY6Il90b2tlbiI7czo0MDoiMjEzQ3pQZkxBWHR2b0ZIQjFPZUJCOFJxY3ppOFlHWExDbXAyRGU1diI7czo2OiJfZmxhc2giO2E6Mjp7czozOiJvbGQiO2E6MDp7fXM6MzoibmV3IjthOjA6e319fQ==', 1771903012),
|
||||
('NJ602ailiCYWtPwJ733AAzUbiu0zjy2WP5JbKvDl', NULL, '195.88.211.210', '', 'YToyOntzOjY6Il90b2tlbiI7czo0MDoiVE12NGxLa2lHMlZkcE1tZWQ5WUlMaURuTUtMNlBVUUZBR3RIM3pYSyI7czo2OiJfZmxhc2giO2E6Mjp7czozOiJvbGQiO2E6MDp7fXM6MzoibmV3IjthOjA6e319fQ==', 1771903823),
|
||||
('oWu1f2obqftNFn8lAEQDPM01nHyOKiNPCNEr8D9b', NULL, '103.189.123.8', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36', 'YTozOntzOjY6Il90b2tlbiI7czo0MDoiajZqeXJHZWgwMWpKcUR4ZFV1Z0JGc1N2cTNwQTZpRGsyOUdBZHBLUiI7czo5OiJfcHJldmlvdXMiO2E6Mjp7czozOiJ1cmwiO3M6MjY6Imh0dHBzOi8vbWVkb3J5Lm15LmlkL2xvZ2luIjtzOjU6InJvdXRlIjtzOjU6ImxvZ2luIjt9czo2OiJfZmxhc2giO2E6Mjp7czozOiJvbGQiO2E6MDp7fXM6MzoibmV3IjthOjA6e319fQ==', 1771904666),
|
||||
('pEaBL9XBz9yhVbVnj7QP9PYhncndRsDrskQld8sI', NULL, '195.88.211.210', '', 'YToyOntzOjY6Il90b2tlbiI7czo0MDoiM21WUXJ0ZlFjVDltRElpQWhONGVnZzFlWmtHNUlJcjNMOVN4bmZiQyI7czo2OiJfZmxhc2giO2E6Mjp7czozOiJvbGQiO2E6MDp7fXM6MzoibmV3IjthOjA6e319fQ==', 1771901475),
|
||||
('PH9UfXWkZDRb0kR0vgIQZMnbuIfCkRQ5gwBEgMeO', 2, '36.79.208.192', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36', 'YTo0OntzOjY6Il90b2tlbiI7czo0MDoib3BRd1hNQzdkUmxyVjZQcHo4TjZmdTZyblhMSzF2cXBRb0ZFeVNGciI7czo5OiJfcHJldmlvdXMiO2E6Mjp7czozOiJ1cmwiO3M6Mjg6Imh0dHBzOi8vbWVkb3J5Lm15LmlkL3Byb2ZpbGUiO3M6NToicm91dGUiO3M6MTI6InByb2ZpbGUuZWRpdCI7fXM6NjoiX2ZsYXNoIjthOjI6e3M6Mzoib2xkIjthOjA6e31zOjM6Im5ldyI7YTowOnt9fXM6NTA6ImxvZ2luX3dlYl81OWJhMzZhZGRjMmIyZjk0MDE1ODBmMDE0YzdmNThlYTRlMzA5ODlkIjtpOjI7fQ==', 1771902801),
|
||||
('R3R6fptYdUCdWWSXRvG846vWByqjTwTfkJYImKNH', NULL, '175.45.186.196', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36', 'YTo0OntzOjY6Il90b2tlbiI7czo0MDoicElydDFubzd0dWJxYUdPUVd3NjRZMXlXNDBnd3NNdlpsUWVWS1NqMSI7czozOiJ1cmwiO2E6MTp7czo4OiJpbnRlbmRlZCI7czozMDoiaHR0cHM6Ly9tZWRvcnkubXkuaWQvZGFzaGJvYXJkIjt9czo5OiJfcHJldmlvdXMiO2E6Mjp7czozOiJ1cmwiO3M6MjY6Imh0dHBzOi8vbWVkb3J5Lm15LmlkL2xvZ2luIjtzOjU6InJvdXRlIjtzOjU6ImxvZ2luIjt9czo2OiJfZmxhc2giO2E6Mjp7czozOiJvbGQiO2E6MDp7fXM6MzoibmV3IjthOjA6e319fQ==', 1771904687),
|
||||
('Se0qp3o9aoWVH67XLfUkeXil7couCQFq23zJF8HI', 1, '36.79.208.192', 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Mobile Safari/537.36', 'YTo0OntzOjY6Il90b2tlbiI7czo0MDoiZWFoaXRQNkRmZE5XVkp5dTR5bGRlaHlUWWFSM1ZrZXJwb1VIREEwaiI7czo5OiJfcHJldmlvdXMiO2E6Mjp7czozOiJ1cmwiO3M6Mjg6Imh0dHBzOi8vbWVkb3J5Lm15LmlkL3Byb2ZpbGUiO3M6NToicm91dGUiO3M6MTI6InByb2ZpbGUuZWRpdCI7fXM6NjoiX2ZsYXNoIjthOjI6e3M6Mzoib2xkIjthOjA6e31zOjM6Im5ldyI7YTowOnt9fXM6NTA6ImxvZ2luX3dlYl81OWJhMzZhZGRjMmIyZjk0MDE1ODBmMDE0YzdmNThlYTRlMzA5ODlkIjtpOjE7fQ==', 1771904090),
|
||||
('SUhF1hfELv5CcNoSdCsxJRnHalfjROwRVE23C8Tr', NULL, '195.88.211.210', '', 'YToyOntzOjY6Il90b2tlbiI7czo0MDoiT1VjQ0t0N1d1TUdMWmJ1bENYSjFCTkNldUVvUER5Rm5Wbk9LQnhMdyI7czo2OiJfZmxhc2giO2E6Mjp7czozOiJvbGQiO2E6MDp7fXM6MzoibmV3IjthOjA6e319fQ==', 1771903000),
|
||||
('UzTpFQbyY333ql8ftUi3tbwwX0NNeX6IUx6lUuCM', NULL, '195.88.211.210', '', 'YToyOntzOjY6Il90b2tlbiI7czo0MDoibDN0dDlLczhXYkpjZ0t2MHlwV2UyQ25DZ2xNRFNyQjNrbkhQZVRGYyI7czo2OiJfZmxhc2giO2E6Mjp7czozOiJvbGQiO2E6MDp7fXM6MzoibmV3IjthOjA6e319fQ==', 1771905580),
|
||||
('yD6o4MW50WcfNU5c0UxkBBaBMu0hOKwoQJdPyNIT', NULL, '195.88.211.210', '', 'YToyOntzOjY6Il90b2tlbiI7czo0MDoiZEZaalJlU0VhVnBDSkM1bXRyckNFMFhCazdXWXF6cE1NY29vZEZWTCI7czo2OiJfZmxhc2giO2E6Mjp7czozOiJvbGQiO2E6MDp7fXM6MzoibmV3IjthOjA6e319fQ==', 1771901045),
|
||||
('yQXyf3tedUwzU8s7pJXnRzjI3Q6GS3RpSrtx9VxP', 2, '114.10.41.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36', 'YTo0OntzOjY6Il90b2tlbiI7czo0MDoicXBNaWZOa0VqaEVaR2dRTTNsR1FEMWdoc3ljSHJFMTQ5OGVlOERhMyI7czo2OiJfZmxhc2giO2E6Mjp7czozOiJvbGQiO2E6MDp7fXM6MzoibmV3IjthOjA6e319czo5OiJfcHJldmlvdXMiO2E6Mjp7czozOiJ1cmwiO3M6MjY6Imh0dHBzOi8vbWVkb3J5Lm15LmlkL3Jlc2VwIjtzOjU6InJvdXRlIjtzOjExOiJyZXNlcC5pbmRleCI7fXM6NTA6ImxvZ2luX3dlYl81OWJhMzZhZGRjMmIyZjk0MDE1ODBmMDE0YzdmNThlYTRlMzA5ODlkIjtpOjI7fQ==', 1771904714);
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktur dari tabel `suppliers`
|
||||
--
|
||||
|
||||
CREATE TABLE `suppliers` (
|
||||
`id` bigint(20) UNSIGNED NOT NULL,
|
||||
`nama` varchar(255) NOT NULL,
|
||||
`alamat` text DEFAULT NULL,
|
||||
`telepon` varchar(255) DEFAULT NULL,
|
||||
`email` varchar(255) DEFAULT NULL,
|
||||
`created_at` timestamp NULL DEFAULT NULL,
|
||||
`updated_at` timestamp NULL DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Dumping data untuk tabel `suppliers`
|
||||
--
|
||||
|
||||
INSERT INTO `suppliers` (`id`, `nama`, `alamat`, `telepon`, `email`, `created_at`, `updated_at`) VALUES
|
||||
(1, 'PT Kimia Farma', 'Jakarta Pusat', '021-1234567', NULL, '2025-12-24 04:52:26', '2025-12-24 04:52:26'),
|
||||
(2, 'PT Kalbe Farma', 'Jakarta Timur', '021-7654321', NULL, '2025-12-24 04:52:26', '2025-12-24 04:52:26'),
|
||||
(3, 'PT Sanbe Farma', 'Bandung', '022-1234567', NULL, '2025-12-24 04:52:26', '2025-12-24 04:52:26');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktur dari tabel `users`
|
||||
--
|
||||
|
||||
CREATE TABLE `users` (
|
||||
`id` bigint(20) UNSIGNED NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`nip` varchar(255) DEFAULT NULL,
|
||||
`email` varchar(255) NOT NULL,
|
||||
`phone` varchar(255) DEFAULT NULL,
|
||||
`gender` varchar(255) DEFAULT NULL,
|
||||
`address` text DEFAULT NULL,
|
||||
`division` varchar(255) DEFAULT NULL,
|
||||
`position` varchar(255) DEFAULT NULL,
|
||||
`profile_photo` varchar(255) DEFAULT NULL,
|
||||
`role` enum('dokter','apoteker') NOT NULL DEFAULT 'apoteker',
|
||||
`email_verified_at` timestamp NULL DEFAULT NULL,
|
||||
`password` varchar(255) NOT NULL,
|
||||
`remember_token` varchar(100) DEFAULT NULL,
|
||||
`created_at` timestamp NULL DEFAULT NULL,
|
||||
`updated_at` timestamp NULL DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Dumping data untuk tabel `users`
|
||||
--
|
||||
|
||||
INSERT INTO `users` (`id`, `name`, `nip`, `email`, `phone`, `gender`, `address`, `division`, `position`, `profile_photo`, `role`, `email_verified_at`, `password`, `remember_token`, `created_at`, `updated_at`) VALUES
|
||||
(1, 'Admin', '0987644876590', 'admin@admin.com', '081333940999', NULL, 'RB konveksi, darungan, babadan', 'apoteker', '-', 'profile-photos/Yp1w8l0LBt5TDVRNRAcmjUXToe7Z01wzo5I2V4yj.png', 'apoteker', NULL, '$2y$12$ezU30KN/7LX0OIaEKB4gxuU.fO/wfMVWk/KCCbyN24xelql7A688i', 'eEkWkkHR5zTNqOh1YT4Rd0S0TUMuwxqIWG4KyEDKcn4ZOc1gU2Vtl0Me0yAo', '2025-12-24 04:52:26', '2026-02-23 09:40:39'),
|
||||
(2, 'Dokter', NULL, 'dokter@dokter.com', NULL, NULL, NULL, NULL, NULL, 'profile-photos/frOqnRsuJM56tmZiqWOAfu7iqNSIKgHBr6XMFCMK.jpg', 'dokter', '2026-02-01 00:18:12', '$2y$12$8RaiDGJxOjydcah39s2uWO.OsLn.0MLOayk82E/pPpofsQiRcD/MG', NULL, '2026-02-01 00:18:12', '2026-02-23 09:30:25');
|
||||
|
||||
--
|
||||
-- Indexes for dumped tables
|
||||
--
|
||||
|
||||
--
|
||||
-- Indeks untuk tabel `cache`
|
||||
--
|
||||
ALTER TABLE `cache`
|
||||
ADD PRIMARY KEY (`key`);
|
||||
|
||||
--
|
||||
-- Indeks untuk tabel `cache_locks`
|
||||
--
|
||||
ALTER TABLE `cache_locks`
|
||||
ADD PRIMARY KEY (`key`);
|
||||
|
||||
--
|
||||
-- Indeks untuk tabel `failed_jobs`
|
||||
--
|
||||
ALTER TABLE `failed_jobs`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `failed_jobs_uuid_unique` (`uuid`);
|
||||
|
||||
--
|
||||
-- Indeks untuk tabel `jobs`
|
||||
--
|
||||
ALTER TABLE `jobs`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `jobs_queue_index` (`queue`);
|
||||
|
||||
--
|
||||
-- Indeks untuk tabel `job_batches`
|
||||
--
|
||||
ALTER TABLE `job_batches`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- Indeks untuk tabel `kategoris`
|
||||
--
|
||||
ALTER TABLE `kategoris`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- Indeks untuk tabel `migrations`
|
||||
--
|
||||
ALTER TABLE `migrations`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- Indeks untuk tabel `obats`
|
||||
--
|
||||
ALTER TABLE `obats`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `obats_kode_unique` (`kode`),
|
||||
ADD KEY `obats_kategori_id_foreign` (`kategori_id`);
|
||||
|
||||
--
|
||||
-- Indeks untuk tabel `obat_keluars`
|
||||
--
|
||||
ALTER TABLE `obat_keluars`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `obat_keluars_obat_id_foreign` (`obat_id`),
|
||||
ADD KEY `obat_keluars_user_id_foreign` (`user_id`),
|
||||
ADD KEY `obat_keluars_obat_masuk_id_foreign` (`obat_masuk_id`);
|
||||
|
||||
--
|
||||
-- Indeks untuk tabel `obat_masuks`
|
||||
--
|
||||
ALTER TABLE `obat_masuks`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `obat_masuks_obat_id_foreign` (`obat_id`),
|
||||
ADD KEY `obat_masuks_supplier_id_foreign` (`supplier_id`),
|
||||
ADD KEY `obat_masuks_user_id_foreign` (`user_id`),
|
||||
ADD KEY `obat_masuks_kategori_id_foreign` (`kategori_id`),
|
||||
ADD KEY `obat_masuks_satuan_id_foreign` (`satuan_id`);
|
||||
|
||||
--
|
||||
-- Indeks untuk tabel `password_reset_tokens`
|
||||
--
|
||||
ALTER TABLE `password_reset_tokens`
|
||||
ADD PRIMARY KEY (`email`);
|
||||
|
||||
--
|
||||
-- Indeks untuk tabel `reseps`
|
||||
--
|
||||
ALTER TABLE `reseps`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `reseps_no_resep_unique` (`no_resep`),
|
||||
ADD KEY `reseps_user_id_foreign` (`user_id`);
|
||||
|
||||
--
|
||||
-- Indeks untuk tabel `resep_items`
|
||||
--
|
||||
ALTER TABLE `resep_items`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `resep_items_resep_id_foreign` (`resep_id`),
|
||||
ADD KEY `resep_items_obat_masuk_id_foreign` (`obat_masuk_id`);
|
||||
|
||||
--
|
||||
-- Indeks untuk tabel `satuans`
|
||||
--
|
||||
ALTER TABLE `satuans`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- Indeks untuk tabel `sessions`
|
||||
--
|
||||
ALTER TABLE `sessions`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `sessions_user_id_index` (`user_id`),
|
||||
ADD KEY `sessions_last_activity_index` (`last_activity`);
|
||||
|
||||
--
|
||||
-- Indeks untuk tabel `suppliers`
|
||||
--
|
||||
ALTER TABLE `suppliers`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- Indeks untuk tabel `users`
|
||||
--
|
||||
ALTER TABLE `users`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `users_email_unique` (`email`);
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT untuk tabel yang dibuang
|
||||
--
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT untuk tabel `failed_jobs`
|
||||
--
|
||||
ALTER TABLE `failed_jobs`
|
||||
MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT untuk tabel `jobs`
|
||||
--
|
||||
ALTER TABLE `jobs`
|
||||
MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT untuk tabel `kategoris`
|
||||
--
|
||||
ALTER TABLE `kategoris`
|
||||
MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT untuk tabel `migrations`
|
||||
--
|
||||
ALTER TABLE `migrations`
|
||||
MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=23;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT untuk tabel `obats`
|
||||
--
|
||||
ALTER TABLE `obats`
|
||||
MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=11;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT untuk tabel `obat_keluars`
|
||||
--
|
||||
ALTER TABLE `obat_keluars`
|
||||
MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=10;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT untuk tabel `obat_masuks`
|
||||
--
|
||||
ALTER TABLE `obat_masuks`
|
||||
MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=10;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT untuk tabel `reseps`
|
||||
--
|
||||
ALTER TABLE `reseps`
|
||||
MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=5;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT untuk tabel `resep_items`
|
||||
--
|
||||
ALTER TABLE `resep_items`
|
||||
MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=5;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT untuk tabel `satuans`
|
||||
--
|
||||
ALTER TABLE `satuans`
|
||||
MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=8;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT untuk tabel `suppliers`
|
||||
--
|
||||
ALTER TABLE `suppliers`
|
||||
MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT untuk tabel `users`
|
||||
--
|
||||
ALTER TABLE `users`
|
||||
MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3;
|
||||
|
||||
--
|
||||
-- Ketidakleluasaan untuk tabel pelimpahan (Dumped Tables)
|
||||
--
|
||||
|
||||
--
|
||||
-- Ketidakleluasaan untuk tabel `obats`
|
||||
--
|
||||
ALTER TABLE `obats`
|
||||
ADD CONSTRAINT `obats_kategori_id_foreign` FOREIGN KEY (`kategori_id`) REFERENCES `kategoris` (`id`) ON DELETE CASCADE;
|
||||
|
||||
--
|
||||
-- Ketidakleluasaan untuk tabel `obat_keluars`
|
||||
--
|
||||
ALTER TABLE `obat_keluars`
|
||||
ADD CONSTRAINT `obat_keluars_obat_id_foreign` FOREIGN KEY (`obat_id`) REFERENCES `obats` (`id`) ON DELETE CASCADE,
|
||||
ADD CONSTRAINT `obat_keluars_obat_masuk_id_foreign` FOREIGN KEY (`obat_masuk_id`) REFERENCES `obat_masuks` (`id`) ON DELETE SET NULL,
|
||||
ADD CONSTRAINT `obat_keluars_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE;
|
||||
|
||||
--
|
||||
-- Ketidakleluasaan untuk tabel `obat_masuks`
|
||||
--
|
||||
ALTER TABLE `obat_masuks`
|
||||
ADD CONSTRAINT `obat_masuks_kategori_id_foreign` FOREIGN KEY (`kategori_id`) REFERENCES `kategoris` (`id`) ON DELETE SET NULL,
|
||||
ADD CONSTRAINT `obat_masuks_obat_id_foreign` FOREIGN KEY (`obat_id`) REFERENCES `obats` (`id`) ON DELETE CASCADE,
|
||||
ADD CONSTRAINT `obat_masuks_satuan_id_foreign` FOREIGN KEY (`satuan_id`) REFERENCES `satuans` (`id`) ON DELETE SET NULL,
|
||||
ADD CONSTRAINT `obat_masuks_supplier_id_foreign` FOREIGN KEY (`supplier_id`) REFERENCES `suppliers` (`id`) ON DELETE SET NULL,
|
||||
ADD CONSTRAINT `obat_masuks_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE;
|
||||
|
||||
--
|
||||
-- Ketidakleluasaan untuk tabel `reseps`
|
||||
--
|
||||
ALTER TABLE `reseps`
|
||||
ADD CONSTRAINT `reseps_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE;
|
||||
|
||||
--
|
||||
-- Ketidakleluasaan untuk tabel `resep_items`
|
||||
--
|
||||
ALTER TABLE `resep_items`
|
||||
ADD CONSTRAINT `resep_items_obat_masuk_id_foreign` FOREIGN KEY (`obat_masuk_id`) REFERENCES `obat_masuks` (`id`) ON DELETE CASCADE,
|
||||
ADD CONSTRAINT `resep_items_resep_id_foreign` FOREIGN KEY (`resep_id`) REFERENCES `reseps` (`id`) ON DELETE CASCADE;
|
||||
COMMIT;
|
||||
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
INFO Running migrations.
|
||||
|
||||
2026_02_08_000003_update_obat_keluars_table 295.04ms DONE
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"$schema": "https://www.schemastore.org/package.json",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "vite build",
|
||||
"dev": "vite"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/forms": "^0.5.2",
|
||||
"@tailwindcss/vite": "^4.0.0",
|
||||
"alpinejs": "^3.4.2",
|
||||
"autoprefixer": "^10.4.2",
|
||||
"axios": "^1.11.0",
|
||||
"concurrently": "^9.0.1",
|
||||
"laravel-vite-plugin": "^2.0.0",
|
||||
"postcss": "^8.4.31",
|
||||
"tailwindcss": "^3.1.0",
|
||||
"vite": "^7.0.7"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,584 @@
|
|||
-- phpMyAdmin SQL Dump
|
||||
-- version 5.2.1
|
||||
-- https://www.phpmyadmin.net/
|
||||
--
|
||||
-- Host: localhost:3306
|
||||
-- Waktu pembuatan: 27 Des 2025 pada 02.22
|
||||
-- Versi server: 8.0.30
|
||||
-- Versi PHP: 8.3.17
|
||||
|
||||
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
|
||||
START TRANSACTION;
|
||||
SET time_zone = "+00:00";
|
||||
|
||||
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
||||
/*!40101 SET NAMES utf8mb4 */;
|
||||
|
||||
--
|
||||
-- Database: `pencatatanobat2`
|
||||
--
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktur dari tabel `cache`
|
||||
--
|
||||
|
||||
CREATE TABLE `cache` (
|
||||
`key` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`value` mediumtext COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`expiration` int NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktur dari tabel `cache_locks`
|
||||
--
|
||||
|
||||
CREATE TABLE `cache_locks` (
|
||||
`key` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`owner` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`expiration` int NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktur dari tabel `failed_jobs`
|
||||
--
|
||||
|
||||
CREATE TABLE `failed_jobs` (
|
||||
`id` bigint UNSIGNED NOT NULL,
|
||||
`uuid` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`connection` text COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`queue` text COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`payload` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`exception` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`failed_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktur dari tabel `jobs`
|
||||
--
|
||||
|
||||
CREATE TABLE `jobs` (
|
||||
`id` bigint UNSIGNED NOT NULL,
|
||||
`queue` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`payload` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`attempts` tinyint UNSIGNED NOT NULL,
|
||||
`reserved_at` int UNSIGNED DEFAULT NULL,
|
||||
`available_at` int UNSIGNED NOT NULL,
|
||||
`created_at` int UNSIGNED NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktur dari tabel `job_batches`
|
||||
--
|
||||
|
||||
CREATE TABLE `job_batches` (
|
||||
`id` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`total_jobs` int NOT NULL,
|
||||
`pending_jobs` int NOT NULL,
|
||||
`failed_jobs` int NOT NULL,
|
||||
`failed_job_ids` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`options` mediumtext COLLATE utf8mb4_unicode_ci,
|
||||
`cancelled_at` int DEFAULT NULL,
|
||||
`created_at` int NOT NULL,
|
||||
`finished_at` int DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktur dari tabel `kategoris`
|
||||
--
|
||||
|
||||
CREATE TABLE `kategoris` (
|
||||
`id` bigint UNSIGNED NOT NULL,
|
||||
`nama` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`keterangan` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`created_at` timestamp NULL DEFAULT NULL,
|
||||
`updated_at` timestamp NULL DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Dumping data untuk tabel `kategoris`
|
||||
--
|
||||
|
||||
INSERT INTO `kategoris` (`id`, `nama`, `keterangan`, `created_at`, `updated_at`) VALUES
|
||||
(1, 'Analgesik', 'Obat pereda nyeri', '2025-12-20 06:50:43', '2025-12-20 06:50:43'),
|
||||
(2, 'Antibiotik', 'Obat anti bakteri', '2025-12-20 06:50:43', '2025-12-20 06:50:43'),
|
||||
(3, 'Antipiretik', 'Obat penurun demam', '2025-12-20 06:50:43', '2025-12-20 06:50:43'),
|
||||
(4, 'Antihipertensi', 'Obat tekanan darah tinggi', '2025-12-20 06:50:43', '2025-12-20 06:50:43'),
|
||||
(5, 'Antidiabetik', 'Obat diabetes', '2025-12-20 06:50:43', '2025-12-20 06:50:43'),
|
||||
(6, 'Vitamin dan Suplemen', 'Suplemen kesehatan', '2025-12-20 06:50:43', '2025-12-20 06:50:43'),
|
||||
(7, 'Test', NULL, '2025-12-20 09:09:40', '2025-12-20 09:09:40');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktur dari tabel `migrations`
|
||||
--
|
||||
|
||||
CREATE TABLE `migrations` (
|
||||
`id` int UNSIGNED NOT NULL,
|
||||
`migration` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`batch` int NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Dumping data untuk tabel `migrations`
|
||||
--
|
||||
|
||||
INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES
|
||||
(1, '0001_01_01_000000_create_users_table', 1),
|
||||
(2, '0001_01_01_000001_create_cache_table', 1),
|
||||
(3, '0001_01_01_000002_create_jobs_table', 1),
|
||||
(4, '2024_01_01_000003_create_kategoris_table', 1),
|
||||
(5, '2024_01_01_000004_create_suppliers_table', 1),
|
||||
(6, '2024_01_01_000005_create_obats_table', 1),
|
||||
(7, '2024_01_01_000006_create_obat_masuks_table', 1),
|
||||
(8, '2024_01_01_000007_create_obat_keluars_table', 1),
|
||||
(9, '2024_01_01_000008_create_satuans_table', 1),
|
||||
(10, '2024_01_01_000009_add_fields_to_obat_masuks_table', 1),
|
||||
(11, '2025_12_20_151320_add_nama_supplier_to_obat_masuks_table', 2),
|
||||
(12, '2025_12_20_152837_update_obat_keluars_use_obat_masuk', 3),
|
||||
(13, '2025_12_20_154137_add_tujuan_pemakaian_to_obat_keluars_table', 4),
|
||||
(14, '2025_12_20_155815_make_obat_id_nullable_on_obat_keluars', 5);
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktur dari tabel `obats`
|
||||
--
|
||||
|
||||
CREATE TABLE `obats` (
|
||||
`id` bigint UNSIGNED NOT NULL,
|
||||
`kategori_id` bigint UNSIGNED NOT NULL,
|
||||
`nama` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`kode` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`satuan` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`deskripsi` text COLLATE utf8mb4_unicode_ci,
|
||||
`created_at` timestamp NULL DEFAULT NULL,
|
||||
`updated_at` timestamp NULL DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Dumping data untuk tabel `obats`
|
||||
--
|
||||
|
||||
INSERT INTO `obats` (`id`, `kategori_id`, `nama`, `kode`, `satuan`, `deskripsi`, `created_at`, `updated_at`) VALUES
|
||||
(1, 1, 'Paracetamol 500mg', 'OBT-001', 'Tablet', NULL, '2025-12-20 06:50:43', '2025-12-20 06:50:43'),
|
||||
(2, 1, 'Ibuprofen 400mg', 'OBT-002', 'Tablet', NULL, '2025-12-20 06:50:43', '2025-12-20 06:50:43'),
|
||||
(3, 2, 'Amoxicillin 500mg', 'OBT-003', 'Kapsul', NULL, '2025-12-20 06:50:43', '2025-12-20 06:50:43'),
|
||||
(4, 2, 'Ciprofloxacin 500mg', 'OBT-004', 'Tablet', NULL, '2025-12-20 06:50:43', '2025-12-20 06:50:43'),
|
||||
(5, 3, 'Aspirin 100mg', 'OBT-005', 'Tablet', NULL, '2025-12-20 06:50:43', '2025-12-20 06:50:43'),
|
||||
(6, 4, 'Amlodipine 5mg', 'OBT-006', 'Tablet', NULL, '2025-12-20 06:50:43', '2025-12-20 06:50:43'),
|
||||
(7, 4, 'Captopril 25mg', 'OBT-007', 'Tablet', NULL, '2025-12-20 06:50:43', '2025-12-20 06:50:43'),
|
||||
(8, 5, 'Metformin 500mg', 'OBT-008', 'Tablet', NULL, '2025-12-20 06:50:43', '2025-12-20 06:50:43'),
|
||||
(9, 6, 'Vitamin C 1000mg', 'OBT-009', 'Tablet', NULL, '2025-12-20 06:50:43', '2025-12-20 06:50:43'),
|
||||
(10, 6, 'Vitamin D3 1000IU', 'OBT-010', 'Kapsul', NULL, '2025-12-20 06:50:43', '2025-12-20 06:50:43');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktur dari tabel `obat_keluars`
|
||||
--
|
||||
|
||||
CREATE TABLE `obat_keluars` (
|
||||
`id` bigint UNSIGNED NOT NULL,
|
||||
`obat_masuk_id` bigint UNSIGNED DEFAULT NULL,
|
||||
`nama_obat` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`obat_id` bigint UNSIGNED DEFAULT NULL,
|
||||
`user_id` bigint UNSIGNED NOT NULL,
|
||||
`kode_batch` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`jumlah` int NOT NULL,
|
||||
`tujuan_pemakaian` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`tanggal_pengeluaran` date NOT NULL,
|
||||
`tanggal_kadaluarsa` date NOT NULL,
|
||||
`no_pengeluaran` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`nama_petugas` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`nama_penerima` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`tujuan` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`catatan` text COLLATE utf8mb4_unicode_ci,
|
||||
`status` enum('terkirim','proses','dibatalkan') COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'proses',
|
||||
`created_at` timestamp NULL DEFAULT NULL,
|
||||
`updated_at` timestamp NULL DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Dumping data untuk tabel `obat_keluars`
|
||||
--
|
||||
|
||||
INSERT INTO `obat_keluars` (`id`, `obat_masuk_id`, `nama_obat`, `obat_id`, `user_id`, `kode_batch`, `jumlah`, `tujuan_pemakaian`, `tanggal_pengeluaran`, `tanggal_kadaluarsa`, `no_pengeluaran`, `nama_petugas`, `nama_penerima`, `tujuan`, `catatan`, `status`, `created_at`, `updated_at`) VALUES
|
||||
(5, 8, 'Panadol', NULL, 1, 'TEST-01', 10, 'ok', '2025-12-20', '2027-12-27', '22', 'Admin', 'ok', NULL, 'ok', 'proses', '2025-12-20 09:00:16', '2025-12-20 09:00:16'),
|
||||
(6, 2, 'Ibuprofen 400mg', NULL, 1, 'BCH-2024-002', 20, 'OK', '2025-12-20', '2025-12-27', '2', 'Admin', 'OK', NULL, 'OK', 'proses', '2025-12-20 09:11:56', '2025-12-20 09:11:56');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktur dari tabel `obat_masuks`
|
||||
--
|
||||
|
||||
CREATE TABLE `obat_masuks` (
|
||||
`id` bigint UNSIGNED NOT NULL,
|
||||
`nama_obat` varchar(200) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`kategori_id` bigint UNSIGNED DEFAULT NULL,
|
||||
`satuan_id` bigint UNSIGNED DEFAULT NULL,
|
||||
`nama_supplier` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`obat_id` bigint UNSIGNED DEFAULT NULL,
|
||||
`supplier_id` bigint UNSIGNED DEFAULT NULL,
|
||||
`user_id` bigint UNSIGNED NOT NULL,
|
||||
`kode_batch` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`stok` int NOT NULL,
|
||||
`harga_beli` decimal(12,2) NOT NULL,
|
||||
`harga_jual` decimal(12,2) NOT NULL,
|
||||
`tanggal_penerimaan` date NOT NULL,
|
||||
`tanggal_kadaluarsa` date NOT NULL,
|
||||
`no_faktur` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`catatan` text COLLATE utf8mb4_unicode_ci,
|
||||
`created_at` timestamp NULL DEFAULT NULL,
|
||||
`updated_at` timestamp NULL DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Dumping data untuk tabel `obat_masuks`
|
||||
--
|
||||
|
||||
INSERT INTO `obat_masuks` (`id`, `nama_obat`, `kategori_id`, `satuan_id`, `nama_supplier`, `obat_id`, `supplier_id`, `user_id`, `kode_batch`, `stok`, `harga_beli`, `harga_jual`, `tanggal_penerimaan`, `tanggal_kadaluarsa`, `no_faktur`, `catatan`, `created_at`, `updated_at`) VALUES
|
||||
(1, 'Paracetamol 500mg', 1, 1, NULL, 1, 1, 1, 'BCH-2024-001', 100, 1500.00, 2500.00, '2025-11-20', '2026-06-20', 'FKT-001', NULL, '2025-12-20 06:50:43', '2025-12-20 06:50:43'),
|
||||
(2, 'Ibuprofen 400mg', 1, 1, NULL, 2, 1, 1, 'BCH-2024-002', 60, 2000.00, 3500.00, '2025-11-25', '2026-02-03', 'FKT-002', NULL, '2025-12-20 06:50:43', '2025-12-20 09:11:56'),
|
||||
(3, 'Amoxicillin 500mg', 2, 2, NULL, 3, 2, 1, 'BCH-2024-003', 150, 3000.00, 5000.00, '2025-11-30', '2026-12-20', 'FKT-003', NULL, '2025-12-20 06:50:43', '2025-12-20 06:50:43'),
|
||||
(4, 'Ciprofloxacin 500mg', 2, 1, NULL, 4, 2, 1, 'BCH-2024-004', 60, 4000.00, 6500.00, '2025-12-05', '2026-01-09', 'FKT-004', NULL, '2025-12-20 06:50:43', '2025-12-20 06:50:43'),
|
||||
(5, 'Aspirin 100mg', 3, 1, NULL, 5, 3, 1, 'BCH-2024-005', 200, 1000.00, 1800.00, '2025-12-10', '2026-03-05', 'FKT-005', NULL, '2025-12-20 06:50:43', '2025-12-20 06:50:43'),
|
||||
(6, 'Amlodipine 5mg', 4, 1, NULL, 6, 1, 1, 'BCH-2024-006', 120, 2500.00, 4000.00, '2025-12-15', '2026-08-20', 'FKT-006', NULL, '2025-12-20 06:50:43', '2025-12-20 06:50:43'),
|
||||
(7, 'Captopril 25mg', 4, 1, NULL, 7, 2, 1, 'BCH-2024-007', 90, 1800.00, 3000.00, '2025-12-17', '2026-01-04', 'FKT-007', NULL, '2025-12-20 06:50:43', '2025-12-20 06:50:43'),
|
||||
(8, 'Panadol', 2, 2, 'PT G', NULL, NULL, 1, 'TEST-01', 90, 100.00, 200.00, '2025-12-20', '2025-12-23', '0I111', 'OKE', '2025-12-20 08:16:11', '2025-12-20 09:13:51'),
|
||||
(9, 'Test', 7, 8, 'PT TEST', NULL, NULL, 1, 'TEST-02', 200, 100.00, 200.00, '2025-12-20', '2027-10-12', '0111', 'OK', '2025-12-20 09:10:53', '2025-12-20 09:10:53');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktur dari tabel `password_reset_tokens`
|
||||
--
|
||||
|
||||
CREATE TABLE `password_reset_tokens` (
|
||||
`email` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`token` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`created_at` timestamp NULL DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktur dari tabel `satuans`
|
||||
--
|
||||
|
||||
CREATE TABLE `satuans` (
|
||||
`id` bigint UNSIGNED NOT NULL,
|
||||
`nama` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`keterangan` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`created_at` timestamp NULL DEFAULT NULL,
|
||||
`updated_at` timestamp NULL DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Dumping data untuk tabel `satuans`
|
||||
--
|
||||
|
||||
INSERT INTO `satuans` (`id`, `nama`, `keterangan`, `created_at`, `updated_at`) VALUES
|
||||
(1, 'Tablet', 'Obat dalam bentuk tablet', '2025-12-20 06:50:43', '2025-12-20 06:50:43'),
|
||||
(2, 'Kapsul', 'Obat dalam bentuk kapsul', '2025-12-20 06:50:43', '2025-12-20 06:50:43'),
|
||||
(3, 'Botol', 'Obat cair dalam botol', '2025-12-20 06:50:43', '2025-12-20 06:50:43'),
|
||||
(4, 'Strip', 'Obat dalam kemasan strip', '2025-12-20 06:50:43', '2025-12-20 06:50:43'),
|
||||
(5, 'Box', 'Obat dalam kemasan box', '2025-12-20 06:50:43', '2025-12-20 06:50:43'),
|
||||
(6, 'Ampul', 'Obat injeksi dalam ampul', '2025-12-20 06:50:43', '2025-12-20 06:50:43'),
|
||||
(7, 'Tube', 'Obat salep/krim dalam tube', '2025-12-20 06:50:43', '2025-12-20 06:50:43'),
|
||||
(8, 'Ml', NULL, '2025-12-20 09:09:53', '2025-12-20 09:09:53');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktur dari tabel `sessions`
|
||||
--
|
||||
|
||||
CREATE TABLE `sessions` (
|
||||
`id` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`user_id` bigint UNSIGNED DEFAULT NULL,
|
||||
`ip_address` varchar(45) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`user_agent` text COLLATE utf8mb4_unicode_ci,
|
||||
`payload` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`last_activity` int NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Dumping data untuk tabel `sessions`
|
||||
--
|
||||
|
||||
INSERT INTO `sessions` (`id`, `user_id`, `ip_address`, `user_agent`, `payload`, `last_activity`) VALUES
|
||||
('CWvMXd923eSL9kHHDSY1XxwZybkx8zMz4ubBafEv', 1, '127.0.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36', 'YTo0OntzOjY6Il90b2tlbiI7czo0MDoiRXVxQWswVGtrNnFoU1gxemZxWXprUkZCa3lDVVdhMXFRRGZBRjVXeSI7czo5OiJfcHJldmlvdXMiO2E6Mjp7czozOiJ1cmwiO3M6NDA6Imh0dHA6Ly8xMjcuMC4wLjE6ODAwMC9vYmF0LWtlbHVhci81L2VkaXQiO3M6NToicm91dGUiO3M6MTY6Im9iYXQta2VsdWFyLmVkaXQiO31zOjY6Il9mbGFzaCI7YToyOntzOjM6Im9sZCI7YTowOnt9czozOiJuZXciO2E6MDp7fX1zOjUwOiJsb2dpbl93ZWJfNTliYTM2YWRkYzJiMmY5NDAxNTgwZjAxNGM3ZjU4ZWE0ZTMwOTg5ZCI7aToxO30=', 1766578721),
|
||||
('XEWcPtymuSTqb64lDcTm8RMIywgdqREpTYsMlHZi', NULL, '127.0.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36 Edg/143.0.0.0', 'YTozOntzOjY6Il90b2tlbiI7czo0MDoiQzF0YnJNV0lQWXV0UkVVVU1yN1pyOTMxV3ZUSVVDUmV1T2ZzNFAzOCI7czo5OiJfcHJldmlvdXMiO2E6Mjp7czozOiJ1cmwiO3M6Mzc6Imh0dHA6Ly8xMjcuMC4wLjE6ODAwMC9mb3Jnb3QtcGFzc3dvcmQiO3M6NToicm91dGUiO3M6MTY6InBhc3N3b3JkLnJlcXVlc3QiO31zOjY6Il9mbGFzaCI7YToyOntzOjM6Im9sZCI7YTowOnt9czozOiJuZXciO2E6MDp7fX19', 1766572325);
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktur dari tabel `suppliers`
|
||||
--
|
||||
|
||||
CREATE TABLE `suppliers` (
|
||||
`id` bigint UNSIGNED NOT NULL,
|
||||
`nama` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`alamat` text COLLATE utf8mb4_unicode_ci,
|
||||
`telepon` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`email` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`created_at` timestamp NULL DEFAULT NULL,
|
||||
`updated_at` timestamp NULL DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Dumping data untuk tabel `suppliers`
|
||||
--
|
||||
|
||||
INSERT INTO `suppliers` (`id`, `nama`, `alamat`, `telepon`, `email`, `created_at`, `updated_at`) VALUES
|
||||
(1, 'PT Kimia Farma', 'Jakarta Pusat', '021-1234567', NULL, '2025-12-20 06:50:43', '2025-12-20 06:50:43'),
|
||||
(2, 'PT Kalbe Farma', 'Jakarta Timur', '021-7654321', NULL, '2025-12-20 06:50:43', '2025-12-20 06:50:43'),
|
||||
(3, 'PT Sanbe Farma', 'Bandung', '022-1234567', NULL, '2025-12-20 06:50:43', '2025-12-20 06:50:43');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Struktur dari tabel `users`
|
||||
--
|
||||
|
||||
CREATE TABLE `users` (
|
||||
`id` bigint UNSIGNED NOT NULL,
|
||||
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`email` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`email_verified_at` timestamp NULL DEFAULT NULL,
|
||||
`password` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`remember_token` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`created_at` timestamp NULL DEFAULT NULL,
|
||||
`updated_at` timestamp NULL DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Dumping data untuk tabel `users`
|
||||
--
|
||||
|
||||
INSERT INTO `users` (`id`, `name`, `email`, `email_verified_at`, `password`, `remember_token`, `created_at`, `updated_at`) VALUES
|
||||
(1, 'Admin', 'admin@admin.com', NULL, '$2y$12$wQzt9xdtR3BSEgostxRbRuEfRuKgfiNIIyU3RYh13uFPD7KrEMgGi', NULL, '2025-12-20 06:50:43', '2025-12-20 06:50:43');
|
||||
|
||||
--
|
||||
-- Indexes for dumped tables
|
||||
--
|
||||
|
||||
--
|
||||
-- Indeks untuk tabel `cache`
|
||||
--
|
||||
ALTER TABLE `cache`
|
||||
ADD PRIMARY KEY (`key`);
|
||||
|
||||
--
|
||||
-- Indeks untuk tabel `cache_locks`
|
||||
--
|
||||
ALTER TABLE `cache_locks`
|
||||
ADD PRIMARY KEY (`key`);
|
||||
|
||||
--
|
||||
-- Indeks untuk tabel `failed_jobs`
|
||||
--
|
||||
ALTER TABLE `failed_jobs`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `failed_jobs_uuid_unique` (`uuid`);
|
||||
|
||||
--
|
||||
-- Indeks untuk tabel `jobs`
|
||||
--
|
||||
ALTER TABLE `jobs`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `jobs_queue_index` (`queue`);
|
||||
|
||||
--
|
||||
-- Indeks untuk tabel `job_batches`
|
||||
--
|
||||
ALTER TABLE `job_batches`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- Indeks untuk tabel `kategoris`
|
||||
--
|
||||
ALTER TABLE `kategoris`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- Indeks untuk tabel `migrations`
|
||||
--
|
||||
ALTER TABLE `migrations`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- Indeks untuk tabel `obats`
|
||||
--
|
||||
ALTER TABLE `obats`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `obats_kode_unique` (`kode`),
|
||||
ADD KEY `obats_kategori_id_foreign` (`kategori_id`);
|
||||
|
||||
--
|
||||
-- Indeks untuk tabel `obat_keluars`
|
||||
--
|
||||
ALTER TABLE `obat_keluars`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `obat_keluars_obat_id_foreign` (`obat_id`),
|
||||
ADD KEY `obat_keluars_user_id_foreign` (`user_id`),
|
||||
ADD KEY `obat_keluars_obat_masuk_id_foreign` (`obat_masuk_id`);
|
||||
|
||||
--
|
||||
-- Indeks untuk tabel `obat_masuks`
|
||||
--
|
||||
ALTER TABLE `obat_masuks`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `obat_masuks_obat_id_foreign` (`obat_id`),
|
||||
ADD KEY `obat_masuks_supplier_id_foreign` (`supplier_id`),
|
||||
ADD KEY `obat_masuks_user_id_foreign` (`user_id`),
|
||||
ADD KEY `obat_masuks_kategori_id_foreign` (`kategori_id`),
|
||||
ADD KEY `obat_masuks_satuan_id_foreign` (`satuan_id`);
|
||||
|
||||
--
|
||||
-- Indeks untuk tabel `password_reset_tokens`
|
||||
--
|
||||
ALTER TABLE `password_reset_tokens`
|
||||
ADD PRIMARY KEY (`email`);
|
||||
|
||||
--
|
||||
-- Indeks untuk tabel `satuans`
|
||||
--
|
||||
ALTER TABLE `satuans`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- Indeks untuk tabel `sessions`
|
||||
--
|
||||
ALTER TABLE `sessions`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `sessions_user_id_index` (`user_id`),
|
||||
ADD KEY `sessions_last_activity_index` (`last_activity`);
|
||||
|
||||
--
|
||||
-- Indeks untuk tabel `suppliers`
|
||||
--
|
||||
ALTER TABLE `suppliers`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- Indeks untuk tabel `users`
|
||||
--
|
||||
ALTER TABLE `users`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `users_email_unique` (`email`);
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT untuk tabel yang dibuang
|
||||
--
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT untuk tabel `failed_jobs`
|
||||
--
|
||||
ALTER TABLE `failed_jobs`
|
||||
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT untuk tabel `jobs`
|
||||
--
|
||||
ALTER TABLE `jobs`
|
||||
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT untuk tabel `kategoris`
|
||||
--
|
||||
ALTER TABLE `kategoris`
|
||||
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=8;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT untuk tabel `migrations`
|
||||
--
|
||||
ALTER TABLE `migrations`
|
||||
MODIFY `id` int UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=15;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT untuk tabel `obats`
|
||||
--
|
||||
ALTER TABLE `obats`
|
||||
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=11;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT untuk tabel `obat_keluars`
|
||||
--
|
||||
ALTER TABLE `obat_keluars`
|
||||
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT untuk tabel `obat_masuks`
|
||||
--
|
||||
ALTER TABLE `obat_masuks`
|
||||
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=10;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT untuk tabel `satuans`
|
||||
--
|
||||
ALTER TABLE `satuans`
|
||||
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=9;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT untuk tabel `suppliers`
|
||||
--
|
||||
ALTER TABLE `suppliers`
|
||||
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT untuk tabel `users`
|
||||
--
|
||||
ALTER TABLE `users`
|
||||
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
|
||||
|
||||
--
|
||||
-- Ketidakleluasaan untuk tabel pelimpahan (Dumped Tables)
|
||||
--
|
||||
|
||||
--
|
||||
-- Ketidakleluasaan untuk tabel `obats`
|
||||
--
|
||||
ALTER TABLE `obats`
|
||||
ADD CONSTRAINT `obats_kategori_id_foreign` FOREIGN KEY (`kategori_id`) REFERENCES `kategoris` (`id`) ON DELETE CASCADE;
|
||||
|
||||
--
|
||||
-- Ketidakleluasaan untuk tabel `obat_keluars`
|
||||
--
|
||||
ALTER TABLE `obat_keluars`
|
||||
ADD CONSTRAINT `obat_keluars_obat_id_foreign` FOREIGN KEY (`obat_id`) REFERENCES `obats` (`id`) ON DELETE CASCADE,
|
||||
ADD CONSTRAINT `obat_keluars_obat_masuk_id_foreign` FOREIGN KEY (`obat_masuk_id`) REFERENCES `obat_masuks` (`id`) ON DELETE SET NULL,
|
||||
ADD CONSTRAINT `obat_keluars_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE;
|
||||
|
||||
--
|
||||
-- Ketidakleluasaan untuk tabel `obat_masuks`
|
||||
--
|
||||
ALTER TABLE `obat_masuks`
|
||||
ADD CONSTRAINT `obat_masuks_kategori_id_foreign` FOREIGN KEY (`kategori_id`) REFERENCES `kategoris` (`id`) ON DELETE SET NULL,
|
||||
ADD CONSTRAINT `obat_masuks_obat_id_foreign` FOREIGN KEY (`obat_id`) REFERENCES `obats` (`id`) ON DELETE CASCADE,
|
||||
ADD CONSTRAINT `obat_masuks_satuan_id_foreign` FOREIGN KEY (`satuan_id`) REFERENCES `satuans` (`id`) ON DELETE SET NULL,
|
||||
ADD CONSTRAINT `obat_masuks_supplier_id_foreign` FOREIGN KEY (`supplier_id`) REFERENCES `suppliers` (`id`) ON DELETE SET NULL,
|
||||
ADD CONSTRAINT `obat_masuks_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE;
|
||||
COMMIT;
|
||||
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
|
||||
bootstrap="vendor/autoload.php"
|
||||
colors="true"
|
||||
>
|
||||
<testsuites>
|
||||
<testsuite name="Unit">
|
||||
<directory>tests/Unit</directory>
|
||||
</testsuite>
|
||||
<testsuite name="Feature">
|
||||
<directory>tests/Feature</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<source>
|
||||
<include>
|
||||
<directory>app</directory>
|
||||
</include>
|
||||
</source>
|
||||
<php>
|
||||
<env name="APP_ENV" value="testing"/>
|
||||
<env name="APP_MAINTENANCE_DRIVER" value="file"/>
|
||||
<env name="BCRYPT_ROUNDS" value="4"/>
|
||||
<env name="BROADCAST_CONNECTION" value="null"/>
|
||||
<env name="CACHE_STORE" value="array"/>
|
||||
<env name="DB_CONNECTION" value="sqlite"/>
|
||||
<env name="DB_DATABASE" value=":memory:"/>
|
||||
<env name="MAIL_MAILER" value="array"/>
|
||||
<env name="QUEUE_CONNECTION" value="sync"/>
|
||||
<env name="SESSION_DRIVER" value="array"/>
|
||||
<env name="PULSE_ENABLED" value="false"/>
|
||||
<env name="TELESCOPE_ENABLED" value="false"/>
|
||||
<env name="NIGHTWATCH_ENABLED" value="false"/>
|
||||
</php>
|
||||
</phpunit>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
export default {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
};
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
<IfModule mod_rewrite.c>
|
||||
<IfModule mod_negotiation.c>
|
||||
Options -MultiViews -Indexes
|
||||
</IfModule>
|
||||
|
||||
RewriteEngine On
|
||||
|
||||
# Handle Authorization Header
|
||||
RewriteCond %{HTTP:Authorization} .
|
||||
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
|
||||
|
||||
# Handle X-XSRF-Token Header
|
||||
RewriteCond %{HTTP:x-xsrf-token} .
|
||||
RewriteRule .* - [E=HTTP_X_XSRF_TOKEN:%{HTTP:X-XSRF-Token}]
|
||||
|
||||
# Redirect Trailing Slashes If Not A Folder...
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_URI} (.+)/$
|
||||
RewriteRule ^ %1 [L,R=301]
|
||||
|
||||
# Send Requests To Front Controller...
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteRule ^ index.php [L]
|
||||
</IfModule>
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
// Helper untuk clear Blade view cache di hosting
|
||||
// HAPUS FILE INI setelah digunakan!
|
||||
$viewCachePath = __DIR__ . '/../storage/framework/views/';
|
||||
$files = glob($viewCachePath . '*.php');
|
||||
$count = 0;
|
||||
foreach ($files as $file) {
|
||||
if (is_file($file)) {
|
||||
unlink($file);
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
echo "✓ Berhasil menghapus {$count} file view cache. Silakan hapus file clear-cache.php ini dari server.";
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Foundation\Application;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
define('LARAVEL_START', microtime(true));
|
||||
|
||||
// Determine if the application is in maintenance mode...
|
||||
if (file_exists($maintenance = __DIR__.'/../storage/framework/maintenance.php')) {
|
||||
require $maintenance;
|
||||
}
|
||||
|
||||
// Register the Composer autoloader...
|
||||
require __DIR__.'/../vendor/autoload.php';
|
||||
|
||||
// Bootstrap Laravel and handle the request...
|
||||
/** @var Application $app */
|
||||
$app = require_once __DIR__.'/../bootstrap/app.php';
|
||||
|
||||
$app->handleRequest(Request::capture());
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue