Compare commits
10
Commits
main
..
2ccdb4f969
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ccdb4f969 | ||
|
|
214b9c82f2 | ||
|
|
912c6c03e3 | ||
|
|
40b3d5d1b8 | ||
|
|
b6679233ea | ||
|
|
96f1d12450 | ||
|
|
27064a1f7e | ||
|
|
ffddee22df | ||
|
|
4bb265e4f1 | ||
|
|
1399f1a2f3 |
No files matched your search
@@ -0,0 +1,66 @@
|
||||
APP_NAME=Laravel
|
||||
APP_ENV=local
|
||||
APP_KEY=base64:kK/3kFWIu/qiax+zB5T9vUcBkazYe6GThmoFXjfHJzU=
|
||||
APP_DEBUG=true
|
||||
APP_URL=https://lis.swandhana.test
|
||||
|
||||
LOG_CHANNEL=daily
|
||||
LOG_DEPRECATIONS_CHANNEL=null
|
||||
LOG_LEVEL=debug
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=db_lis
|
||||
DB_USERNAME=root
|
||||
DB_PASSWORD=bismillah
|
||||
|
||||
BROADCAST_DRIVER=pusher
|
||||
CACHE_DRIVER=file
|
||||
FILESYSTEM_DISK=local
|
||||
QUEUE_CONNECTION=sync
|
||||
QUEUE_DRIVER=sync
|
||||
SESSION_DRIVER=database
|
||||
SESSION_LIFETIME=1440
|
||||
|
||||
MEMCACHED_HOST=127.0.0.1
|
||||
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
|
||||
MAIL_DRIVER=smtp
|
||||
MAIL_HOST=smtp.gmail.com
|
||||
MAIL_PORT=587
|
||||
MAIL_USERNAME=[email protected]
|
||||
MAIL_PASSWORD=
|
||||
MAIL_ENCRYPTION=tls
|
||||
QUEUE_DRIVER=sync
|
||||
MAIL_FROM_NAME="Duidev Mailler"
|
||||
MAIL_FROM_ADDRESS=[email protected]
|
||||
|
||||
AWS_ACCESS_KEY_ID=
|
||||
AWS_SECRET_ACCESS_KEY=
|
||||
AWS_DEFAULT_REGION=us-east-1
|
||||
AWS_BUCKET=
|
||||
AWS_USE_PATH_STYLE_ENDPOINT=false
|
||||
|
||||
PUSHER_APP_ID=878723
|
||||
PUSHER_APP_KEY=461fe095afe037987c11
|
||||
PUSHER_APP_SECRET=c03b22f3d6c148426f67
|
||||
PUSHER_APP_CLUSTER=ap1
|
||||
PUSHER_HOST=
|
||||
PUSHER_PORT=443
|
||||
PUSHER_SCHEME=https
|
||||
|
||||
VITE_APP_NAME="${APP_NAME}"
|
||||
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
|
||||
VITE_PUSHER_HOST="${PUSHER_HOST}"
|
||||
VITE_PUSHER_PORT="${PUSHER_PORT}"
|
||||
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
|
||||
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
||||
|
||||
BPJS_CONSID="2112121"
|
||||
BPJS_SECRET_KEY="121212121"
|
||||
BPJS_BASE_URL="https://new-api.bpjs-kesehatan.go.id:8080"
|
||||
BPJS_SERVICE_NAME="new-vclaim-rest"
|
||||
@@ -0,0 +1,59 @@
|
||||
APP_NAME=Laravel
|
||||
APP_ENV=local
|
||||
APP_KEY=
|
||||
APP_DEBUG=true
|
||||
APP_URL=http://localhost
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
LOG_DEPRECATIONS_CHANNEL=null
|
||||
LOG_LEVEL=debug
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=laravel
|
||||
DB_USERNAME=root
|
||||
DB_PASSWORD=
|
||||
|
||||
BROADCAST_DRIVER=log
|
||||
CACHE_DRIVER=file
|
||||
FILESYSTEM_DISK=local
|
||||
QUEUE_CONNECTION=sync
|
||||
SESSION_DRIVER=file
|
||||
SESSION_LIFETIME=120
|
||||
|
||||
MEMCACHED_HOST=127.0.0.1
|
||||
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
|
||||
MAIL_MAILER=smtp
|
||||
MAIL_HOST=mailpit
|
||||
MAIL_PORT=1025
|
||||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=null
|
||||
MAIL_FROM_ADDRESS="[email protected]"
|
||||
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
|
||||
|
||||
PUSHER_APP_ID=
|
||||
PUSHER_APP_KEY=
|
||||
PUSHER_APP_SECRET=
|
||||
PUSHER_HOST=
|
||||
PUSHER_PORT=443
|
||||
PUSHER_SCHEME=https
|
||||
PUSHER_APP_CLUSTER=mt1
|
||||
|
||||
VITE_APP_NAME="${APP_NAME}"
|
||||
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
|
||||
VITE_PUSHER_HOST="${PUSHER_HOST}"
|
||||
VITE_PUSHER_PORT="${PUSHER_PORT}"
|
||||
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
|
||||
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
# Ignore environment files
|
||||
|
||||
mergekemain.sh
|
||||
# Ignore Laravel cache, logs, and storage
|
||||
/htdocs/.DS_Store
|
||||
/htdocs/.env
|
||||
|
||||
/htdocs/vendor/
|
||||
/htdocs/database/seeders/data/
|
||||
/htdocs/listenerlis/
|
||||
|
||||
|
||||
/htdocs/storage/*.key
|
||||
/htdocs/storage/logs/*
|
||||
/htdocs/storage/framework/cache/*
|
||||
/htdocs/storage/framework/sessions/*
|
||||
/htdocs/storage/framework/views/*
|
||||
/node_modules/
|
||||
/npm-debug.log
|
||||
/yarn-error.log
|
||||
# Ignore bootstrap cache
|
||||
/htdocs/bootstrap/cache/*
|
||||
.env
|
||||
!/htdocs/bootstrap/cache/.gitignore
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
.DS_Store
|
||||
@@ -1,630 +1,55 @@
|
||||
# MyLIS-RSSA
|
||||
### Microbiology Laboratory Information System
|
||||
# LIS (Laboratory Information System)
|
||||
|
||||
---
|
||||
**Laboratory Information System (LIS)** adalah sistem yang digunakan untuk mengelola informasi terkait dengan laboratorium, mulai dari manajemen data sampel, hasil tes, hingga laporan dan pengolahan data terkait laboratorium.
|
||||
|
||||
## Bahasa Indonesia
|
||||
## Developer
|
||||
Aplikasi ini dikembangkan oleh tim pengembang dari **CV. Swandhana**.
|
||||
|
||||
**MyLIS-RSSA** adalah ekosistem aplikasi Laboratory Information System untuk layanan mikrobiologi RSUD Dr. Saiful Anwar. Repo ini berisi aplikasi web/backend Laravel, aplikasi pendamping mobile/desktop Flutter, dan service listener Python untuk komunikasi alat laboratorium.
|
||||
|
||||
Sistem ini membantu alur kerja laboratorium mulai dari penerimaan order, registrasi sampel, pengelompokan pemeriksaan, input expertise, verifikasi hasil, pelaporan, notifikasi nilai kritis, sampai integrasi dengan SIMRS dan instrumen laboratorium.
|
||||
|
||||
---
|
||||
|
||||
### Aplikasi di Dalam Repo
|
||||
|
||||
#### 1. LIS Web & Backend (`htdocs`)
|
||||
|
||||
Aplikasi utama berbasis Laravel untuk operasional laboratorium. Modul ini menangani autentikasi, dashboard, pendaftaran pasien/sampel, daftar pemeriksaan, template hasil, expertise, laporan, label/barcode, logbook, biorepository, gudang BHP, API mobile, backup cloud, dan integrasi SIMRS.
|
||||
|
||||
Ringkasan fungsi:
|
||||
|
||||
- Registrasi order dari SIMRS melalui endpoint `registerpasien`, `registerulang`, dan `registerjson`.
|
||||
- Pengelolaan pasien, dokter, poli/ruangan, user, template jawaban, dan subjawaban.
|
||||
- Worklist pemeriksaan mikrobiologi berdasarkan buku/kategori sampel.
|
||||
- Input dan cetak hasil pemeriksaan, adendum, label, form, dan laporan.
|
||||
- Dashboard Early Warning System dan notifikasi nilai kritis.
|
||||
- Modul logbook PPDS/SPV, biorepository, dan SIMBHP.
|
||||
- API `/api/mobile` untuk aplikasi MyLIS Flutter.
|
||||
- Utilitas backup/restore database ke cloud dan export/simulasi payload register API.
|
||||
|
||||
#### 2. MyLIS Flutter (`mylis`)
|
||||
|
||||
Aplikasi mobile/desktop pendamping untuk akses cepat ke LIS Laravel. Aplikasi ini dipakai untuk login, cek koneksi server, dashboard, pencarian sampel, scanner barcode, Early Warning System, penerimaan pekerjaan awal, daftar pemeriksaan, detail pemeriksaan, notifikasi nilai kritis, dan pengisian expertise native.
|
||||
|
||||
Screen expertise yang tersedia:
|
||||
|
||||
- `CCI`
|
||||
- `Kultur`
|
||||
- `Pewarna Langsung`
|
||||
- `TBC`
|
||||
- `Viral Load`
|
||||
- `IgM IgG Leptospira`
|
||||
- `PCR COVID`
|
||||
|
||||
#### 3. Listener Instrumen (`listener`)
|
||||
|
||||
Service Python untuk komunikasi dengan instrumen laboratorium, terutama jalur serial/TCP dan GeneXpert. Service ini membaca, memproses, dan mengirim pesan instrumen seperti ASTM/HL7, lalu menyimpan atau meneruskan data ke database LIS.
|
||||
|
||||
Ringkasan fungsi:
|
||||
|
||||
- Listener TCP untuk GeneXpert.
|
||||
- Komunikasi serial untuk perangkat seperti Vitek dan BACTEC.
|
||||
- Mapping kode pemeriksaan LIS ke host test code alat.
|
||||
- Antrean order instrumen dan pemrosesan hasil.
|
||||
- Logging harian dan log per thread untuk troubleshooting.
|
||||
|
||||
---
|
||||
|
||||
### Cara Kerja Aplikasi
|
||||
|
||||
Alur utama sistem:
|
||||
|
||||
```text
|
||||
SIMRS / user web
|
||||
-> Laravel LIS menerima order dan data pasien
|
||||
-> Sampel masuk ke worklist mikrobiologi
|
||||
-> Petugas menerima, memproses, dan mengisi hasil/expertise
|
||||
-> Supervisor melakukan verifikasi atau finalisasi
|
||||
-> Hasil dicetak, dikirim, atau diekstrak kembali ke SIMRS
|
||||
```
|
||||
|
||||
Alur mobile:
|
||||
|
||||
```text
|
||||
MyLIS Flutter
|
||||
-> login ke Laravel melalui /api/mobile/login
|
||||
-> mengambil dashboard, worklist, detail pemeriksaan, dan template expertise
|
||||
-> menyimpan draft, preliminary, final, atau kirim ke SPV
|
||||
-> Laravel menyimpan perubahan ke database LIS
|
||||
```
|
||||
|
||||
Alur instrumen:
|
||||
|
||||
```text
|
||||
Instrumen laboratorium
|
||||
-> listener Python menerima ASTM/HL7/serial/TCP
|
||||
-> data diparse dan dicocokkan dengan order/sampel
|
||||
-> hasil atau status instrumen disimpan ke database
|
||||
-> Laravel menampilkan hasil untuk proses validasi dan pelaporan
|
||||
```
|
||||
|
||||
Alur backup cloud:
|
||||
|
||||
```text
|
||||
Server production
|
||||
-> pg_dump database
|
||||
-> upload file .backup secara chunked ke cloud
|
||||
-> restore dapat dilakukan dengan download backup terbaru dan pg_restore
|
||||
```
|
||||
|
||||
Detail backup, restore, export payload `registerApi`, dan simulasi kirim data SIMRS tersedia di [htdocs/README.md](/Users/duidev/htdocs/lis/htdocs/README.md).
|
||||
|
||||
---
|
||||
|
||||
### Teknologi
|
||||
|
||||
- **Backend**: Laravel 10, PHP 8.1+ dengan platform Composer PHP 8.4.
|
||||
- **API & Auth**: Laravel route API, token terenkripsi untuk mobile, Laravel Sanctum/Passport tersedia di dependency.
|
||||
- **Frontend Web**: Blade, Bootstrap, jQuery, DataTables, Livewire 3, Vite.
|
||||
- **Database**: konfigurasi `.env` mendukung MySQL; deployment/backup production juga memakai PostgreSQL untuk database `lismikro`.
|
||||
- **Reporting & Dokumen**: TCPDF, FPDI, PhpSpreadsheet, QR/barcode generator.
|
||||
- **Integrasi**: HL7, ASTM, serial communication, FTP, HTTP client Guzzle, bridging BPJS.
|
||||
- **Mobile/Desktop**: Flutter, Dart, Material UI, HTTP client, shared preferences, URL launcher, mobile scanner.
|
||||
- **Listener Engine**: Python 3, Flask, SQLAlchemy, psycopg2, pyserial, hl7.
|
||||
- **Runtime Ops**: Artisan commands, cron backup, optional Docker Compose.
|
||||
|
||||
---
|
||||
|
||||
### Instalasi LIS Web & Backend (`htdocs`)
|
||||
|
||||
Prasyarat:
|
||||
|
||||
- PHP 8.1 atau lebih baru.
|
||||
- Composer.
|
||||
- Node.js dan npm.
|
||||
- Database MySQL atau PostgreSQL sesuai konfigurasi deployment.
|
||||
- Ekstensi PHP yang dibutuhkan Laravel dan package proyek.
|
||||
|
||||
Langkah instalasi:
|
||||
|
||||
```bash
|
||||
cd htdocs
|
||||
composer install
|
||||
npm install
|
||||
cp .env.example .env
|
||||
php artisan key:generate
|
||||
```
|
||||
|
||||
Sesuaikan konfigurasi utama di `.env`:
|
||||
|
||||
```env
|
||||
APP_URL=https://lis.swandhana.test
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=db_lis
|
||||
DB_USERNAME=root
|
||||
DB_PASSWORD=
|
||||
```
|
||||
|
||||
Jalankan migrasi bila database target memang disiapkan dari migration project:
|
||||
|
||||
```bash
|
||||
php artisan migrate
|
||||
```
|
||||
|
||||
Jalankan aplikasi lokal:
|
||||
|
||||
```bash
|
||||
php artisan serve
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Build aset production:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
Perintah verifikasi yang umum:
|
||||
|
||||
```bash
|
||||
php artisan route:list
|
||||
php artisan route:list --path=mobile
|
||||
php -l app/Http/Controllers/MobileApiController.php
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Instalasi MyLIS Flutter (`mylis`)
|
||||
|
||||
Prasyarat:
|
||||
|
||||
- Flutter SDK sesuai `pubspec.yaml` (`Dart SDK ^3.12.2`).
|
||||
- Android Studio/Xcode sesuai platform target.
|
||||
- Server Laravel LIS yang bisa diakses dari device atau simulator.
|
||||
|
||||
Langkah instalasi:
|
||||
|
||||
```bash
|
||||
cd mylis
|
||||
flutter pub get
|
||||
flutter run
|
||||
```
|
||||
|
||||
Jalankan dengan URL Laravel tertentu:
|
||||
|
||||
```bash
|
||||
flutter run --dart-define=LIS_BASE_URL=https://lis.swandhana.test/
|
||||
```
|
||||
|
||||
Build aplikasi:
|
||||
|
||||
```bash
|
||||
flutter build apk --debug
|
||||
flutter build ios --debug --no-codesign
|
||||
flutter build macos --debug
|
||||
```
|
||||
|
||||
Verifikasi:
|
||||
|
||||
```bash
|
||||
flutter analyze
|
||||
flutter test
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Instalasi Listener Instrumen (`listener`)
|
||||
|
||||
Prasyarat:
|
||||
|
||||
- Python 3.
|
||||
- Akses jaringan ke database LIS dan instrumen laboratorium.
|
||||
- Akses port serial/TCP sesuai alat yang dipakai.
|
||||
|
||||
Langkah instalasi:
|
||||
|
||||
```bash
|
||||
cd listener
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
Jalankan listener utama:
|
||||
|
||||
```bash
|
||||
python app.py
|
||||
```
|
||||
|
||||
Jalankan listener GeneXpert khusus:
|
||||
|
||||
```bash
|
||||
python geneexpert.py
|
||||
```
|
||||
|
||||
Catatan konfigurasi:
|
||||
|
||||
- `app.py` dan `geneexpert.py` masih menyimpan mapping IP, port, perangkat, dan database di dalam file.
|
||||
- Pastikan `DATABASE_URL`, `TARGET_MAPPING`, `DEVICE_CONFIGS`, port serial, dan port TCP sesuai lingkungan produksi.
|
||||
- Default port penting: TCP GeneXpert `6001` dan HTTP trigger `6002`.
|
||||
|
||||
---
|
||||
|
||||
### API Mobile Utama
|
||||
|
||||
Prefix endpoint:
|
||||
|
||||
```text
|
||||
/api/mobile
|
||||
```
|
||||
|
||||
Endpoint utama:
|
||||
|
||||
- `GET /api/mobile/ping`
|
||||
- `POST /api/mobile/login`
|
||||
- `GET /api/mobile/dashboard`
|
||||
- `GET /api/mobile/critical-values`
|
||||
- `POST /api/mobile/critical-values/{id}/mark-read`
|
||||
- `GET /api/mobile/early-warning`
|
||||
- `GET /api/mobile/examinations/search`
|
||||
- `GET /api/mobile/initial-work/samples`
|
||||
- `POST /api/mobile/initial-work/samples/{id}/accept`
|
||||
- `POST /api/mobile/initial-work/samples/{id}/reject`
|
||||
- `GET /api/mobile/books/{master}/examinations`
|
||||
- `GET /api/mobile/examinations/{id}`
|
||||
- `GET /api/mobile/examinations/{id}/expertise`
|
||||
- `POST /api/mobile/examinations/{id}/expertise/template`
|
||||
- `POST /api/mobile/examinations/{id}/expertise`
|
||||
|
||||
---
|
||||
|
||||
### Manual Book
|
||||
|
||||
Panduan pengguna dapat diunduh melalui:
|
||||
|
||||
```text
|
||||
http://10.10.123.218/manual.pdf
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Dukungan Pengembangan
|
||||
|
||||
Aplikasi ini dikembangkan oleh **CV. Swandhana**.
|
||||
|
||||
Alamat:
|
||||
|
||||
```text
|
||||
**Alamat:**
|
||||
Jl. Lamandau 18A, Bunulrejo, Blimbing, Malang
|
||||
```
|
||||
|
||||
Kontak WhatsApp:
|
||||
|
||||
```text
|
||||
**Nomor Telepon (WA):**
|
||||
081359108565
|
||||
```
|
||||
|
||||
Pengembangan juga didukung oleh kolaborasi antara pengembang dan AI assistant seperti ChatGPT/Gemini untuk dokumentasi, refactoring, dan percepatan pekerjaan teknis.
|
||||
## Manual Book
|
||||
Untuk panduan pengguna atau manual book dari LIS, dapat diunduh melalui link berikut:
|
||||
[Download Manual Book](http://10.10.123.218/manual.pdf)
|
||||
|
||||
## Fitur
|
||||
- Pengelolaan data sampel laboratorium
|
||||
- Pengolahan dan analisis hasil tes
|
||||
- Pembuatan laporan otomatis
|
||||
- Integrasi dengan perangkat laboratorium (optional)
|
||||
|
||||
## Instalasi
|
||||
1. Clone repository ini ke sistem lokal Anda:
|
||||
```bash
|
||||
git clone https://git.rssa.top/dwi_vendor/lis/repository.git
|
||||
```
|
||||
2. Masuk ke dalam folder proyek:
|
||||
```bash
|
||||
cd repository
|
||||
```
|
||||
3. Instal dependensi yang diperlukan:
|
||||
```bash
|
||||
composer install
|
||||
```
|
||||
|
||||
4. Konfigurasi `.env` sesuai dengan kebutuhan aplikasi Anda.
|
||||
5. Jalankan server aplikasi:
|
||||
```bash
|
||||
php artisan serve
|
||||
```
|
||||
|
||||
## Teknologi yang Digunakan
|
||||
- **Laravel** (PHP Framework)
|
||||
- **MySQL** (Database)
|
||||
- **Bootstrap** (Frontend)
|
||||
- **jQuery** (Frontend)
|
||||
|
||||
## Kontribusi
|
||||
Jika Anda ingin berkontribusi pada proyek ini, silakan buat **pull request** atau **issue** terkait.
|
||||
|
||||
## Lisensi
|
||||
Proyek ini dilisensikan di bawah lisensi MIT. Lihat file **LICENSE** untuk informasi lebih lanjut.
|
||||
|
||||
---
|
||||
|
||||
### Lisensi
|
||||
|
||||
Proyek ini menggunakan lisensi **MIT**. Lihat file `LICENSE` jika tersedia di distribusi project.
|
||||
|
||||
---
|
||||
|
||||
## English Version
|
||||
|
||||
**MyLIS-RSSA** is a Laboratory Information System ecosystem for the microbiology service at RSUD Dr. Saiful Anwar. This repository contains a Laravel web/backend application, a Flutter mobile/desktop companion app, and a Python listener service for laboratory instrument communication.
|
||||
|
||||
The system supports laboratory workflows from order intake, sample registration, examination grouping, expertise entry, result verification, reporting, critical value notification, to SIMRS and instrument integration.
|
||||
|
||||
---
|
||||
|
||||
### Applications in This Repository
|
||||
|
||||
#### 1. LIS Web & Backend (`htdocs`)
|
||||
|
||||
The main Laravel application for laboratory operations. It handles authentication, dashboards, patient/sample registration, examination lists, result templates, expertise, reports, labels/barcodes, logbooks, biorepository, BHP inventory, mobile APIs, cloud backup, and SIMRS integration.
|
||||
|
||||
Main capabilities:
|
||||
|
||||
- Order registration from SIMRS through `registerpasien`, `registerulang`, and `registerjson`.
|
||||
- Management of patients, doctors, clinics/rooms, users, answer templates, and sub-answers.
|
||||
- Microbiology worklists grouped by sample book/category.
|
||||
- Result entry, result printing, addendum, labels, forms, and reports.
|
||||
- Early Warning System dashboard and critical value notifications.
|
||||
- PPDS/SPV logbook, biorepository, and SIMBHP modules.
|
||||
- `/api/mobile` endpoints for the MyLIS Flutter app.
|
||||
- Cloud database backup/restore and register API payload export/simulation utilities.
|
||||
|
||||
#### 2. MyLIS Flutter (`mylis`)
|
||||
|
||||
A mobile/desktop companion app for fast access to the Laravel LIS. It supports login, server ping, dashboard, sample search, barcode scanning, Early Warning System, initial work acceptance, examination lists, examination details, critical value notifications, and native expertise entry.
|
||||
|
||||
Available expertise screens:
|
||||
|
||||
- `CCI`
|
||||
- `Kultur`
|
||||
- `Pewarna Langsung`
|
||||
- `TBC`
|
||||
- `Viral Load`
|
||||
- `IgM IgG Leptospira`
|
||||
- `PCR COVID`
|
||||
|
||||
#### 3. Instrument Listener (`listener`)
|
||||
|
||||
A Python service for laboratory instrument communication, especially serial/TCP and GeneXpert workflows. It receives, processes, and sends instrument messages such as ASTM/HL7, then stores or forwards the data to the LIS database.
|
||||
|
||||
Main capabilities:
|
||||
|
||||
- TCP listener for GeneXpert.
|
||||
- Serial communication for devices such as Vitek and BACTEC.
|
||||
- Mapping from LIS examination names to instrument host test codes.
|
||||
- Instrument order queue and result processing.
|
||||
- Daily logs and per-thread logs for troubleshooting.
|
||||
|
||||
---
|
||||
|
||||
### How the System Works
|
||||
|
||||
Main workflow:
|
||||
|
||||
```text
|
||||
SIMRS / web user
|
||||
-> Laravel LIS receives orders and patient data
|
||||
-> samples enter the microbiology worklist
|
||||
-> staff accept, process, and enter results/expertise
|
||||
-> supervisor verifies or finalizes the result
|
||||
-> result is printed, sent, or extracted back to SIMRS
|
||||
```
|
||||
|
||||
Mobile workflow:
|
||||
|
||||
```text
|
||||
MyLIS Flutter
|
||||
-> logs in to Laravel through /api/mobile/login
|
||||
-> fetches dashboard, worklist, examination details, and expertise templates
|
||||
-> saves draft, preliminary, final, or sends to SPV
|
||||
-> Laravel persists the changes to the LIS database
|
||||
```
|
||||
|
||||
Instrument workflow:
|
||||
|
||||
```text
|
||||
Laboratory instrument
|
||||
-> Python listener receives ASTM/HL7/serial/TCP messages
|
||||
-> data is parsed and matched with orders/samples
|
||||
-> instrument results or statuses are stored in the database
|
||||
-> Laravel displays the result for validation and reporting
|
||||
```
|
||||
|
||||
Cloud backup workflow:
|
||||
|
||||
```text
|
||||
Production server
|
||||
-> pg_dump database
|
||||
-> uploads .backup file to cloud in chunks
|
||||
-> restore can download the latest backup and run pg_restore
|
||||
```
|
||||
|
||||
Detailed backup, restore, `registerApi` payload export, and SIMRS payload simulation notes are available in [htdocs/README.md](/Users/duidev/htdocs/lis/htdocs/README.md).
|
||||
|
||||
---
|
||||
|
||||
### Technology Stack
|
||||
|
||||
- **Backend**: Laravel 10, PHP 8.1+ with Composer platform PHP 8.4.
|
||||
- **API & Auth**: Laravel API routes, encrypted token for mobile, Laravel Sanctum/Passport available in dependencies.
|
||||
- **Web Frontend**: Blade, Bootstrap, jQuery, DataTables, Livewire 3, Vite.
|
||||
- **Database**: `.env` supports MySQL; production/backup deployment also uses PostgreSQL for the `lismikro` database.
|
||||
- **Reporting & Documents**: TCPDF, FPDI, PhpSpreadsheet, QR/barcode generator.
|
||||
- **Integrations**: HL7, ASTM, serial communication, FTP, Guzzle HTTP client, BPJS bridging.
|
||||
- **Mobile/Desktop**: Flutter, Dart, Material UI, HTTP client, shared preferences, URL launcher, mobile scanner.
|
||||
- **Listener Engine**: Python 3, Flask, SQLAlchemy, psycopg2, pyserial, hl7.
|
||||
- **Runtime Ops**: Artisan commands, cron backup, optional Docker Compose.
|
||||
|
||||
---
|
||||
|
||||
### Installing LIS Web & Backend (`htdocs`)
|
||||
|
||||
Requirements:
|
||||
|
||||
- PHP 8.1 or newer.
|
||||
- Composer.
|
||||
- Node.js and npm.
|
||||
- MySQL or PostgreSQL database depending on the target deployment.
|
||||
- PHP extensions required by Laravel and this project's packages.
|
||||
|
||||
Installation:
|
||||
|
||||
```bash
|
||||
cd htdocs
|
||||
composer install
|
||||
npm install
|
||||
cp .env.example .env
|
||||
php artisan key:generate
|
||||
```
|
||||
|
||||
Adjust the main `.env` configuration:
|
||||
|
||||
```env
|
||||
APP_URL=https://lis.swandhana.test
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=db_lis
|
||||
DB_USERNAME=root
|
||||
DB_PASSWORD=
|
||||
```
|
||||
|
||||
Run migrations when the target database is meant to be prepared from this project's migrations:
|
||||
|
||||
```bash
|
||||
php artisan migrate
|
||||
```
|
||||
|
||||
Run locally:
|
||||
|
||||
```bash
|
||||
php artisan serve
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Build production assets:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
Common verification commands:
|
||||
|
||||
```bash
|
||||
php artisan route:list
|
||||
php artisan route:list --path=mobile
|
||||
php -l app/Http/Controllers/MobileApiController.php
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Installing MyLIS Flutter (`mylis`)
|
||||
|
||||
Requirements:
|
||||
|
||||
- Flutter SDK matching `pubspec.yaml` (`Dart SDK ^3.12.2`).
|
||||
- Android Studio/Xcode depending on the target platform.
|
||||
- A Laravel LIS server reachable from the device or simulator.
|
||||
|
||||
Installation:
|
||||
|
||||
```bash
|
||||
cd mylis
|
||||
flutter pub get
|
||||
flutter run
|
||||
```
|
||||
|
||||
Run with a specific Laravel URL:
|
||||
|
||||
```bash
|
||||
flutter run --dart-define=LIS_BASE_URL=https://lis.swandhana.test/
|
||||
```
|
||||
|
||||
Build:
|
||||
|
||||
```bash
|
||||
flutter build apk --debug
|
||||
flutter build ios --debug --no-codesign
|
||||
flutter build macos --debug
|
||||
```
|
||||
|
||||
Verification:
|
||||
|
||||
```bash
|
||||
flutter analyze
|
||||
flutter test
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Installing Instrument Listener (`listener`)
|
||||
|
||||
Requirements:
|
||||
|
||||
- Python 3.
|
||||
- Network access to the LIS database and laboratory instruments.
|
||||
- Serial/TCP port access according to the target instruments.
|
||||
|
||||
Installation:
|
||||
|
||||
```bash
|
||||
cd listener
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
Run the main listener:
|
||||
|
||||
```bash
|
||||
python app.py
|
||||
```
|
||||
|
||||
Run the dedicated GeneXpert listener:
|
||||
|
||||
```bash
|
||||
python geneexpert.py
|
||||
```
|
||||
|
||||
Configuration notes:
|
||||
|
||||
- `app.py` and `geneexpert.py` still keep IP, port, device, and database mapping inside the files.
|
||||
- Make sure `DATABASE_URL`, `TARGET_MAPPING`, `DEVICE_CONFIGS`, serial ports, and TCP ports match the production environment.
|
||||
- Important default ports: GeneXpert TCP `6001` and HTTP trigger `6002`.
|
||||
|
||||
---
|
||||
|
||||
### Main Mobile API
|
||||
|
||||
Endpoint prefix:
|
||||
|
||||
```text
|
||||
/api/mobile
|
||||
```
|
||||
|
||||
Main endpoints:
|
||||
|
||||
- `GET /api/mobile/ping`
|
||||
- `POST /api/mobile/login`
|
||||
- `GET /api/mobile/dashboard`
|
||||
- `GET /api/mobile/critical-values`
|
||||
- `POST /api/mobile/critical-values/{id}/mark-read`
|
||||
- `GET /api/mobile/early-warning`
|
||||
- `GET /api/mobile/examinations/search`
|
||||
- `GET /api/mobile/initial-work/samples`
|
||||
- `POST /api/mobile/initial-work/samples/{id}/accept`
|
||||
- `POST /api/mobile/initial-work/samples/{id}/reject`
|
||||
- `GET /api/mobile/books/{master}/examinations`
|
||||
- `GET /api/mobile/examinations/{id}`
|
||||
- `GET /api/mobile/examinations/{id}/expertise`
|
||||
- `POST /api/mobile/examinations/{id}/expertise/template`
|
||||
- `POST /api/mobile/examinations/{id}/expertise`
|
||||
|
||||
---
|
||||
|
||||
### Manual Book
|
||||
|
||||
User manual:
|
||||
|
||||
```text
|
||||
http://10.10.123.218/manual.pdf
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Development Support
|
||||
|
||||
This application is developed by **CV. Swandhana**.
|
||||
|
||||
Address:
|
||||
|
||||
```text
|
||||
Jl. Lamandau 18A, Bunulrejo, Blimbing, Malang
|
||||
```
|
||||
|
||||
WhatsApp:
|
||||
|
||||
```text
|
||||
081359108565
|
||||
```
|
||||
|
||||
Development is also supported by collaboration between developers and AI assistants such as ChatGPT/Gemini for documentation, refactoring, and technical acceleration.
|
||||
|
||||
---
|
||||
|
||||
### License
|
||||
|
||||
This project uses the **MIT** license. See the `LICENSE` file if it is available in the project distribution.
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use App\Services\AstmMessageService;
|
||||
use App\DataListiner;
|
||||
|
||||
class ProcessAstmMessages extends Command
|
||||
{
|
||||
protected $signature = 'astm:process-messages';
|
||||
protected $description = 'Process pending ASTM messages';
|
||||
|
||||
private $astmMessageService;
|
||||
|
||||
public function __construct(AstmMessageService $astmMessageService)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->astmMessageService = $astmMessageService;
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
// Ambil data dari DataListener
|
||||
$dataListener = DataListiner::whereNull('processed')->get();
|
||||
if ($dataListener) {
|
||||
$jumlah = count($dataListener);
|
||||
$pesan = $this->astmMessageService->processAstmMessages($dataListener);
|
||||
$this->info($jumlah.' Message processed '.$pesan.' at '.date('Y-m-d H:i:s'));
|
||||
} else {
|
||||
$this->info('Skipped Proses at '.date('Y-m-d H:i:s'));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console;
|
||||
|
||||
use Illuminate\Console\Scheduling\Schedule;
|
||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||
|
||||
class Kernel extends ConsoleKernel
|
||||
{
|
||||
/**
|
||||
* Define the application's command schedule.
|
||||
*/
|
||||
protected function schedule(Schedule $schedule): void
|
||||
{
|
||||
// $schedule->command('inspire')->hourly();
|
||||
//$schedule->command('lab:sync-results')->everyThirtyMinutes();
|
||||
//$schedule->command('app:sync-lab-results-f-t-p')->everyThirtyMinutes();
|
||||
//$schedule->command('app:sync-lab-results-serial')->everyThirtyMinutes();
|
||||
$schedule->command('astm:process-messages')->everyFiveMinutes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the commands for the application.
|
||||
*/
|
||||
protected function commands(): void
|
||||
{
|
||||
$this->load(__DIR__.'/Commands');
|
||||
|
||||
require base_path('routes/console.php');
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load diff
@@ -0,0 +1,264 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Poli;
|
||||
use App\Periksa;
|
||||
use App\Dokter;
|
||||
use App\Ruangan;
|
||||
use App\Subjawaban;
|
||||
use App\Jawaban;
|
||||
use App\Pasien;
|
||||
use App\User;
|
||||
use App\Jadwalperiksa;
|
||||
use Carbon\Carbon;
|
||||
use DateTime;
|
||||
use Session;
|
||||
|
||||
class ListController extends Controller
|
||||
{
|
||||
public function index() {
|
||||
if (Session::get('previlage') == ''){
|
||||
return redirect('/login');
|
||||
} else {
|
||||
$polis = Poli::all();
|
||||
$ruangans = Ruangan::all();
|
||||
$dokters = Dokter::all();
|
||||
$answers = Jawaban::all();
|
||||
$details = Subjawaban::all();
|
||||
$ruangpolis = Ruangan::groupBy('poli')->select('poli')->get();
|
||||
$data = [];
|
||||
$i = 0;
|
||||
foreach ($ruangpolis as $ruangpoli) {
|
||||
$j = 0;
|
||||
$ruangpoli = $ruangpoli->poli;
|
||||
$rooms = Ruangan::where('poli', $ruangpoli)->get();
|
||||
foreach ($rooms as $room) {
|
||||
$data['ruangans'][$i][$j]['id'] = $room->id;
|
||||
$data['ruangans'][$i][$j]['ruangan'] = $room->ruangan;
|
||||
$j++;
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
|
||||
$x = 0;
|
||||
foreach ($ruangpolis as $ruangpoli) {
|
||||
$data['ruangpolis'][$x] = $ruangpoli->poli;
|
||||
$x++;
|
||||
}
|
||||
|
||||
$data['polis'] = $polis;
|
||||
$data['dokters'] = $dokters;
|
||||
$data['answers'] = $answers;
|
||||
$data['details'] = $details;
|
||||
|
||||
return view('admin.list', $data);
|
||||
}
|
||||
|
||||
}
|
||||
public function getList(Request $request) {
|
||||
$jenis = $request->input('jenis');
|
||||
$mulai = $request->input('mulai');
|
||||
$akhir = $request->input('akhir');
|
||||
$lokasi = $request->input('poli');
|
||||
$valcari = $request->input('valcari');
|
||||
$master = $request->input('master');
|
||||
if ($jenis == 'verificationppds'){
|
||||
$valcari = $request->input('poli');
|
||||
}
|
||||
$total = 0;
|
||||
$data = $this->getDataBasedOnMaster($master, $jenis, $mulai, $akhir, $valcari);
|
||||
if (!empty($data)){
|
||||
$dataArray = $data->get()->toArray();
|
||||
$total = count($dataArray);
|
||||
$arraylist = array_map(function ($list) use ($master) {
|
||||
$tgl = $list['tgllahirpasien'];
|
||||
$poli_id = $list['poli_id'];
|
||||
$foto = $list['foto'];
|
||||
$baca = $list['baca'];
|
||||
$export = $list['export'];
|
||||
$nofoto = $list['nofoto'];
|
||||
$noregister = $list['noregister'];
|
||||
$usia = $list['usia'];
|
||||
$urgensi = $list['urgensi'];
|
||||
$reques = $list['reques'];
|
||||
$ruangan = $list['ruangan'];
|
||||
$daftar = $list['daftar'];
|
||||
$status = $list['status'];
|
||||
$asalpasien = $list['asalpasien'];
|
||||
$dokter_id = $list['dokter_id'];
|
||||
$ppdssenior = $list['ppdssenior'];
|
||||
$middleppds = $list['middleppds'];
|
||||
$ppdsjunior = $list['ppdsjunior'];
|
||||
$middleppds2= $list['ppdsmiddle2'];
|
||||
$ppdsjunior2= $list['ppdsjunior2'];
|
||||
$pasiedin = $list['pasien_id'];
|
||||
$keterangan = $list['keterangan'];
|
||||
$kesimpulan = $list['kesimpulan'];
|
||||
$verifikasi = $list['verifikasi'];
|
||||
$nama = $list['nmpasien'];
|
||||
$jk = $list['jkpasien'];
|
||||
$telpon = $list['tlppasien'];
|
||||
$alamat = $list['alamatpasien'];
|
||||
$tgllahir = $list['tgllahirpasien'];
|
||||
$ktp = $list['ktp'];
|
||||
$bpjs = $list['bpjs'];
|
||||
$nmpendaftar= $list['pendaftar'];
|
||||
if ($nmpendaftar == 'supervisor' OR $nmpendaftar == 'admin' OR $nmpendaftar == 'analis' OR $nmpendaftar == 'ppds' OR $nmpendaftar == 'developer'){
|
||||
$nmpendaftar = $list['nmpendaftar'];
|
||||
} else {
|
||||
$nmpendaftar = 'SIMRS';
|
||||
}
|
||||
$from = $verifikasi ? \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $verifikasi) : null;
|
||||
$to = $verifikasi ? \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $verifikasi)->toString() : '';
|
||||
if ($from && $from->isValid()) {
|
||||
$durasi = $verifikasi ? \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $verifikasi)->diffForHumans($from) : 'On Progress';
|
||||
} else {
|
||||
$durasi = 'On Progress';
|
||||
}
|
||||
if ($middleppds2 != 0){
|
||||
$ppdsas = 'Middle';
|
||||
$otherppds = $list['nmppdsmiddle2'];
|
||||
} else {
|
||||
$ppdsas = 'Junior';
|
||||
$otherppds = $ppdsjunior2;
|
||||
$otherppds = $list['nmppdsjunior2'];
|
||||
}
|
||||
|
||||
$arrdaftar = explode(" ", $daftar);
|
||||
$tgldaftar = $arrdaftar[0];
|
||||
$jamdaftar = $arrdaftar[1];
|
||||
$daftar = $tgldaftar;
|
||||
$tglfoto = $foto ?: date("Y-m-d H:i:s");
|
||||
$datatampilan = $this->setStatusStyles($status, $nofoto, $noregister, $nama, $telpon, $jk, $usia, $urgensi, $reques, $ruangan, $daftar, $asalpasien);
|
||||
return [
|
||||
'asalpasien' => $list['asalpasien'],
|
||||
'tlsnofoto' => $datatampilan['nofoto'],
|
||||
'tlsnoregister' => $datatampilan['noregister'],
|
||||
'tlsnama' => $datatampilan['nama'],
|
||||
'tlsjk' => $datatampilan['jk'],
|
||||
'tlsusia' => $datatampilan['usia'],
|
||||
'tlsurgensi' => ($list['urgensi'] == 'CITO') ? '<span style="background-color: red;">C I T O</span>' : $datatampilan['urgensi'],
|
||||
'tlsreques' => $datatampilan['reques'],
|
||||
'tlsruangan' => $list['ruangan'],
|
||||
'tlsdaftar' => $datatampilan['daftar'],
|
||||
'tlsstatus' => $datatampilan['status'],
|
||||
'id' => $list['id'],
|
||||
'nofoto' => $nofoto,
|
||||
'noregister' => $noregister,
|
||||
'nama' => $nama,
|
||||
'jk' => $jk,
|
||||
'usia' => $usia,
|
||||
'urgensi' => $urgensi,
|
||||
'poli' => $reques,
|
||||
'idpasien' => $pasiedin,
|
||||
'ruangan' => $ruangan,
|
||||
'daftar' => $list['daftar'],
|
||||
'daftartgl' => $daftar,
|
||||
'daftarjam' => $jamdaftar,
|
||||
'status' => $status,
|
||||
'dokter' => $master != 'kiriman' ? $list['nmdokter'] : '',
|
||||
'ppds1' => $master != 'kiriman' ? $list['nmppdssenior'] : '',
|
||||
'ppds2' => $master != 'kiriman' ? $list['nmmiddleppds'] : '',
|
||||
'ppds3' => $master != 'kiriman' ? $list['nmppdsjunior'] : '',
|
||||
'keterangan' => $keterangan,
|
||||
'kesimpulan' => $kesimpulan,
|
||||
'noloket' => $list['noloket'],
|
||||
'idruangan' => $list['ruangan_id'],
|
||||
'iddokter' => $list['dokter_id'],
|
||||
'ppdssenior' => $list['ppdssenior'],
|
||||
'middleppds' => $list['middleppds'],
|
||||
'ppdsjunior' => $list['ppdsjunior'],
|
||||
'diagnosa' => $list['diagnosa'],
|
||||
'diagnosa2' => $list['diagnosa2'],
|
||||
'kd_spesimen' => $list['kd_spesimen'],
|
||||
'nm_spesimen' => $list['nm_spesimen'],
|
||||
'berat' => $list['berat'],
|
||||
'klinis' => $list['klinis'],
|
||||
'klinisi' => $list['klinisi'],
|
||||
'filefoto' => $list['filefoto'],
|
||||
'dlp' => $list['dlp'],
|
||||
'analis' => $list['analis'],
|
||||
'excutor' => $list['excutor'],
|
||||
'modality' => $list['modality'],
|
||||
'viewfoto' => $list['foto'],
|
||||
'tglfoto' => $tglfoto,
|
||||
'nmppdssenior' => $list['nmppdssenior'],
|
||||
'nmmiddleppds' => $list['nmmiddleppds'],
|
||||
'nmppdsjunior' => $list['nmppdsjunior'],
|
||||
'nmppdsmiddle2' => $list['nmppdsmiddle2'],
|
||||
'nmppdsjunior2' => $list['nmppdsjunior2'],
|
||||
'nmanalis' => $list['nmanalis'],
|
||||
'nmexcutor' => $list['nmexcutor'],
|
||||
'telpon' => $list['tlppasien'],
|
||||
'asuransi' => $list['asuransi'],
|
||||
'tgllahir' => $list['tgllahirpasien'],
|
||||
'alamat' => $list['alamatpasien'],
|
||||
'poli_id' => $list['poli_id'],
|
||||
'nmpendaftar' => $nmpendaftar,
|
||||
'timestamp1' => $from ? $from->toString() : null,
|
||||
'timestamp2' => $to,
|
||||
'durasi' => $durasi,
|
||||
'ppdsas' => $ppdsas,
|
||||
'otherppds' => $otherppds,
|
||||
'ktp' => $ktp,
|
||||
'bpjs' => $bpjs,
|
||||
];
|
||||
}, $dataArray);
|
||||
}
|
||||
$response = [
|
||||
'message' => 'List Laporan',
|
||||
'data' => $arraylist,
|
||||
'total' => $total
|
||||
];
|
||||
return response()->json($response, 200);
|
||||
}
|
||||
public function listDetail(Request $request) {
|
||||
$id = $request->input('id');
|
||||
$periksa = DB::table('periksa')->where('id', $id)->first();
|
||||
echo json_encode($periksa);
|
||||
}
|
||||
public function delete(Request $request) {
|
||||
$id = $request->input('val01');
|
||||
$alasan = $request->input('val02');
|
||||
$tabel = $request->input('val03');
|
||||
if ($alasan == ''){
|
||||
return response()->json(['icon' => 'error', 'warna' => '#bf441d', 'status' => 'Gagal', 'message' => 'Mohon isi semua form']);
|
||||
return back();
|
||||
} else {
|
||||
if ($tabel == 'aktif'){
|
||||
$alasan = 'Dibatalkan dengan alasan '.$alasan;
|
||||
$input = Periksa::where('id', $id)->update([
|
||||
'noloket' => null,
|
||||
'status' => $alasan
|
||||
]);
|
||||
$pesan = 'Order Expertise Canceled';
|
||||
} else if ($tabel == 'arsip'){
|
||||
$total = 0;
|
||||
$input = Periksa::whereIn('id', $id)->update([
|
||||
'status'=> 'Arsip'
|
||||
]);
|
||||
if ($input){
|
||||
$total++;
|
||||
}
|
||||
$pesan = 'Expertise Archieved '.$total;
|
||||
} else {
|
||||
$alasan = 'Dibatalkan dengan alasan '.$alasan;
|
||||
$input = Jadwalperiksa::where('id', $id)->update([
|
||||
'noloket' => null,
|
||||
'status' => $alasan
|
||||
]);
|
||||
$pesan = 'Schedulling Canceled';
|
||||
}
|
||||
if ($input){
|
||||
return response()->json(['icon' => 'success', 'warna' => '#5ba035', 'status' => 'Sukses', 'message' => $pesan]);
|
||||
return back();
|
||||
}else {
|
||||
return response()->json(['icon' => 'error', 'warna' => '#bf441d', 'status' => 'Gagal', 'message' => 'System Down, please try again in a few years...']);
|
||||
return back();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+42
-33
@@ -105,39 +105,48 @@ class PasienController extends Controller
|
||||
]);
|
||||
} else {
|
||||
try {
|
||||
$client = new Client();
|
||||
$res = $client->request('GET', 'https://gomed.rssa.my.id/api/account/pasien', ['query' => ['limit' => 10, 'nomedis' => $norm]]);
|
||||
$response_data = json_decode($res->getBody()->getContents());
|
||||
if (isset($response_data->response[0])) {
|
||||
$hasil = $response_data->response[0];
|
||||
$nama = $hasil->Nama;
|
||||
$alamat = $hasil->Alamat;
|
||||
$telpon = $hasil->Telp;
|
||||
$kota = $hasil->Kota;
|
||||
$kelamin = $hasil->JenisKelamin;
|
||||
$tgllahir = $hasil->tanggal_lahir;
|
||||
return response()->json([
|
||||
'id' => 'new',
|
||||
'norm' => $norm,
|
||||
'telpon' => $telpon,
|
||||
'nama' => $nama,
|
||||
'tgl_lahir' => date('d-m-Y', strtotime($tgllahir)),
|
||||
'jk' => $kelamin,
|
||||
'alamat' => $alamat,
|
||||
'kota' => $kota,
|
||||
]);
|
||||
} else {
|
||||
return response()->json([
|
||||
'id' => '',
|
||||
'telpon' => '000000000',
|
||||
'norm' => $norm,
|
||||
'nama' => '',
|
||||
'tgl_lahir' => date("d-m-Y"),
|
||||
'jk' => 'L',
|
||||
'alamat' => 'Malang',
|
||||
'kota' => 'Malang',
|
||||
]);
|
||||
}
|
||||
$client = new Client();
|
||||
$res = $client->request('GET', 'http://10.10.123.51:8000/mr/'.$norm);
|
||||
$response_data = json_decode($res->getBody()->getContents());
|
||||
if (isset($response_data[0])) {
|
||||
$hasil = $response_data[0];
|
||||
$nama = $hasil->Nama;
|
||||
$alamat = $hasil->Alamat;
|
||||
$telpon = $hasil->Telp;
|
||||
$kota = $hasil->Kota;
|
||||
$kelamin = $hasil->JenisKelamin;
|
||||
$tgllahir = $hasil->tanggal_lahir;
|
||||
$nik = $hasil->nik;
|
||||
$bpjs = $hasil->bpjs;
|
||||
if ($kelamin == 'WANITA'){
|
||||
$kelamin = 'P';
|
||||
} else { $kelamin = 'L'; }
|
||||
return response()->json([
|
||||
'id' => 'new',
|
||||
'norm' => $norm,
|
||||
'telpon' => $telpon,
|
||||
'nama' => $nama,
|
||||
'tgl_lahir' => $tgllahir,
|
||||
'jk' => $kelamin,
|
||||
'alamat' => $alamat,
|
||||
'kota' => $kota,
|
||||
'nik' => $nik,
|
||||
'bpjs' => $bpjs,
|
||||
]);
|
||||
} else {
|
||||
return response()->json([
|
||||
'id' => '',
|
||||
'telpon' => '000000000',
|
||||
'norm' => $norm,
|
||||
'nama' => '',
|
||||
'tgl_lahir' => date("d-m-Y"),
|
||||
'jk' => 'L',
|
||||
'alamat' => 'Malang',
|
||||
'kota' => 'Malang',
|
||||
'nik' => '',
|
||||
'bpjs' => '',
|
||||
]);
|
||||
}
|
||||
}catch (Exception $e) {
|
||||
return response()->json([
|
||||
'id' => '',
|
||||
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Poli;
|
||||
use App\Ruangan;
|
||||
use App\Organisms;
|
||||
|
||||
use Validator;
|
||||
use Session;
|
||||
|
||||
class PoliController extends Controller
|
||||
{
|
||||
public function index() {
|
||||
if (Session::get('previlage') == ''){
|
||||
return redirect('/login');
|
||||
} else {
|
||||
$data = [];
|
||||
$data['polis'] = Poli::all();
|
||||
$data['ruangans'] = Ruangan::all();
|
||||
return view('admin.poli', $data);
|
||||
}
|
||||
}
|
||||
public function storePoli(Request $request) {
|
||||
$validator = Validator::make($request->all(), [
|
||||
'poli' => 'required',
|
||||
'poli' => 'required',
|
||||
'modaliti' => 'required'
|
||||
]);
|
||||
if($validator->fails()) {
|
||||
return response()->json(['status' => 'error', 'message' => 'Please fill input field or fill with right input']);
|
||||
} else {
|
||||
$poli = $request->input('poli');
|
||||
$subpoli = $request->input('subpoli');
|
||||
$subsubpoli = $request->input('subsubpoli');
|
||||
$modaliti = $request->input('modaliti');
|
||||
Poli::create([
|
||||
'poli' => $request->input('poli'),
|
||||
'subpoli' => $request->input('subpoli'),
|
||||
'subsubpoli'=> $request->input('subsubpoli'),
|
||||
'modaliti' => $request->input('modaliti'),
|
||||
'modaliti2' => $request->input('modaliti2')
|
||||
]);
|
||||
$tulis = 'Data '.$poli.' '.$subpoli.' '.$subsubpoli.' Saved..!!';
|
||||
return response()->json(['status' => 'success', 'message' => $tulis]);
|
||||
}
|
||||
}
|
||||
public function getListPoli() {
|
||||
$results = Poli::orderBy('subpoli', 'ASC')->get();
|
||||
echo json_encode($results);
|
||||
}
|
||||
public function updatePoli(Request $request) {
|
||||
$validator = Validator::make($request->all(), [
|
||||
'id' => 'required',
|
||||
'poli' => 'required',
|
||||
'subpoli' => 'required',
|
||||
'modaliti' => 'required'
|
||||
]);
|
||||
if($validator->fails()) {
|
||||
return response()->json(['status' => 'error', 'message' => 'Please fill input field or fill with right input']);
|
||||
} else {
|
||||
$id = $request->input('id');
|
||||
$poli = $request->input('poli');
|
||||
$subpoli = $request->input('subpoli');
|
||||
$subsubpoli = $request->input('subsubpoli');
|
||||
Poli::where('id', $id)->update([
|
||||
'poli' => $poli,
|
||||
'subpoli' => $subpoli,
|
||||
'subsubpoli'=> $subsubpoli,
|
||||
'modaliti' => $request->input('modaliti'),
|
||||
'modaliti2' => $request->input('modaliti2')
|
||||
]);
|
||||
$tulis = 'Data '.$poli.' '.$subpoli.' '.$subsubpoli.' Updated..!!';
|
||||
return response()->json(['status' => 'success', 'message' => $tulis]);
|
||||
}
|
||||
}
|
||||
public function deletePoli(Request $request) {
|
||||
$id = $request->id;
|
||||
$poli = Poli::find($id);
|
||||
$poli->delete();
|
||||
return back();
|
||||
}
|
||||
public function storeRuangan(Request $request) {
|
||||
$validator = Validator::make($request->all(), [
|
||||
'poli' => 'required',
|
||||
'ruangan' => 'required'
|
||||
]);
|
||||
if($validator->fails()) {
|
||||
return response()->json(['status' => 'error', 'message' => 'Please fill input field or fill with right input']);
|
||||
} else {
|
||||
Ruangan::create([
|
||||
'poli' => $request->input('poli'),
|
||||
'ruangan' => $request->input('ruangan')
|
||||
]);
|
||||
Session::flash('message', 'Data berhasil disimpan');
|
||||
Session::flash('alert-class', 'alert-success');
|
||||
return back();
|
||||
}
|
||||
}
|
||||
public function getListRuangan(Request $request) {
|
||||
$results = Ruangan::all();
|
||||
echo json_encode($results);
|
||||
}
|
||||
public function updateRuangan(Request $request) {
|
||||
$validator = Validator::make($request->all(), [
|
||||
'id' => 'required',
|
||||
'poli' => 'required',
|
||||
'ruangan' => 'required'
|
||||
]);
|
||||
if($validator->fails()) {
|
||||
return response()->json(['status' => 'error', 'message' => 'Please fill input field or fill with right input']);
|
||||
} else {
|
||||
$id = $request->input('id');
|
||||
Ruangan::where('id', $id)->update([
|
||||
'poli' => $request->input('poli'),
|
||||
'ruangan' => $request->input('ruangan')
|
||||
]);
|
||||
}
|
||||
}
|
||||
public function deleteRuangan(Request $request) {
|
||||
$id = $request->id;
|
||||
$ruangan = Ruangan::find($id);
|
||||
$ruangan->delete();
|
||||
return back();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,309 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Poli;
|
||||
use App\Logbook;
|
||||
use App\User;
|
||||
use App\Periksa;
|
||||
use App\Dokter;
|
||||
use App\Pasien;
|
||||
use App\Jadwalperiksa;
|
||||
use App\Riwayat;
|
||||
use DateTime;
|
||||
use Carbon\Carbon;
|
||||
use Session;
|
||||
|
||||
class ReportController extends Controller
|
||||
{
|
||||
public function index() {
|
||||
if (Session::get('previlage') == ''){
|
||||
return redirect('/login');
|
||||
} else {
|
||||
return view('admin.report');
|
||||
}
|
||||
}
|
||||
public function rekapPeriksa(Request $request) {
|
||||
set_time_limit(0);
|
||||
$bulan = $request->input('bulan');
|
||||
$tahun = $request->input('tahun');
|
||||
if ($bulan == 'ALL' || $bulan == 'Pick Month') {
|
||||
$orderbydate = Periksa::selectRaw('SUM(id) as jumlah, DATE(daftar) as day')->whereYear('daftar', $tahun)->groupBy(DB::raw('daftar'))->orderBy('daftar', 'ASC')->get();
|
||||
$bulan = '';
|
||||
} else {
|
||||
$tglcari = $tahun . '-' . str_pad($bulan, 2, '0', STR_PAD_LEFT);
|
||||
$orderbydate = Periksa::selectRaw('SUM(id) as jumlah, DATE(daftar) as day')->where('day', 'LIKE', '%' . $tglcari . '%')->groupBy(DB::raw('daftar'))->orderBy('daftar', 'ASC')->get();
|
||||
$bulanNames = [
|
||||
'01' => 'BULAN JANUARI',
|
||||
'02' => 'BULAN FEBRUARI',
|
||||
'03' => 'BULAN MARET',
|
||||
'04' => 'BULAN APRIL',
|
||||
'05' => 'BULAN MEI',
|
||||
'06' => 'BULAN JUNI',
|
||||
'07' => 'BULAN JULI',
|
||||
'08' => 'BULAN AGUSTUS',
|
||||
'09' => 'BULAN SEPTEMBER',
|
||||
'10' => 'BULAN OKTOBER',
|
||||
'11' => 'BULAN NOVEMBER',
|
||||
'12' => 'BULAN DESEMBER',
|
||||
];
|
||||
$bulan = $bulanNames[$bulan] ?? $bulan;
|
||||
}
|
||||
$data = [];
|
||||
$data['bulan'] = $bulan;
|
||||
$data['tahun'] = $tahun;
|
||||
$data['orderbydate']= $orderbydate;
|
||||
$generatetabel = view('cetak.rekap_periksa_table', $data)->render();
|
||||
echo $generatetabel;
|
||||
}
|
||||
protected static function getPasienData($result) {
|
||||
return [
|
||||
'nama' => $result->nmpasien,
|
||||
'tgl' => $result->tgllahirpasien,
|
||||
'jk' => $result->jkpasien,
|
||||
];
|
||||
}
|
||||
protected static function updateTotals($totals, $asuransi, $urgensi, $jk) {
|
||||
if ($jk == 'L') {
|
||||
$totals['m']++;
|
||||
} else {
|
||||
$totals['f']++;
|
||||
}
|
||||
|
||||
if ($asuransi == 'JKN') {
|
||||
$totals['jkn']++;
|
||||
} elseif ($asuransi == 'Umum') {
|
||||
$totals['umum']++;
|
||||
} elseif ($asuransi == 'TAG') {
|
||||
$totals['tag']++;
|
||||
} elseif ($asuransi == 'GCU') {
|
||||
$totals['gcu']++;
|
||||
} elseif ($asuransi == 'Billing') {
|
||||
$totals['bill']++;
|
||||
} else {
|
||||
$totals['swasta']++;
|
||||
}
|
||||
|
||||
if ($urgensi == 'Elective') {
|
||||
$totals['electiv']++;
|
||||
} else {
|
||||
$totals['cito']++;
|
||||
}
|
||||
|
||||
return $totals;
|
||||
}
|
||||
protected static function mapResultToArray($result) {
|
||||
$nmpasien = $result->nmpasien;
|
||||
$tgl = $result->tgllahirpasien;
|
||||
$jk = $result->jkpasien;
|
||||
$jenis = $result->reques;
|
||||
$tlppasien = $result->tlppasien;
|
||||
$nofoto = $result->nofoto;
|
||||
$verifikasi = $result->verifikasi;
|
||||
$tanggal = $result->daftar;
|
||||
$tanggalfoto = $result->foto;
|
||||
$asuransi = $result->asuransi;
|
||||
$urgensi = $result->urgensi;
|
||||
$from = \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $result->daftar);
|
||||
if (is_null($verifikasi)){
|
||||
$verifikasi = '';
|
||||
$to = '';
|
||||
$durasi = 'On Progress';
|
||||
} else {
|
||||
$to = \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $verifikasi);
|
||||
$durasi = $to->diffForHumans($from);
|
||||
}
|
||||
$arrayttllhr = explode("-", $tgl);
|
||||
if (isset($arrayttllhr[2])){
|
||||
$yy = $arrayttllhr[0];
|
||||
$mm = $arrayttllhr[1];
|
||||
$dd = $arrayttllhr[2];
|
||||
$tgllahir = $dd.'-'.$mm.'-'.$yy;
|
||||
} else { $tgllahir = $tgl; }
|
||||
$arrayttl = explode(" ", $tanggal);
|
||||
$tanggal = $arrayttl[0];
|
||||
if ($jk == 'L') {
|
||||
$l = '1';
|
||||
$p = '';
|
||||
} else {
|
||||
$l = '';
|
||||
$p = '1';
|
||||
}
|
||||
if ($asuransi == 'JKN') {
|
||||
$jkn = '1';
|
||||
$umm = '';
|
||||
$swasta = '';
|
||||
$gcu = '';
|
||||
$tag = '';
|
||||
$bill = '';
|
||||
} else if ($asuransi == 'Umum') {
|
||||
$jkn = '';
|
||||
$umm = '1';
|
||||
$swasta = '';
|
||||
$gcu = '';
|
||||
$tag = '';
|
||||
$bill = '';
|
||||
} else if ($asuransi == 'TAG') {
|
||||
$jkn = '';
|
||||
$umm = '';
|
||||
$swasta = '';
|
||||
$gcu = '';
|
||||
$bill = '';
|
||||
$tag = '1';
|
||||
} else if ($asuransi == 'GCU') {
|
||||
$jkn = '';
|
||||
$umm = '';
|
||||
$swasta = '';
|
||||
$gcu = '1';
|
||||
$tag = '';
|
||||
$bill = '';
|
||||
} else if ($asuransi == 'Billing') {
|
||||
$jkn = '';
|
||||
$umm = '';
|
||||
$swasta = '';
|
||||
$gcu = '';
|
||||
$bill = '1';
|
||||
$tag = '';
|
||||
} else {
|
||||
$jkn = '';
|
||||
$umm = '';
|
||||
$swasta = '1';
|
||||
$gcu = '';
|
||||
$tag = '';
|
||||
$bill = '';
|
||||
}
|
||||
if ($urgensi == 'Elective') {
|
||||
$ele = '1';
|
||||
$cito = '';
|
||||
} else {
|
||||
$ele = '';
|
||||
$cito = '1';
|
||||
}
|
||||
$getjennofoto = explode("-", $nofoto);
|
||||
$jenis = $getjennofoto[0].' '.$jenis;
|
||||
return [
|
||||
'id' => $result->id,
|
||||
'filefoto' => '<a href="' . url('/') . '/hasil/' . $result->nofoto . '" target="_blank">' . $result->nofoto . '</a>',
|
||||
'l' => $l,
|
||||
'p' => $p,
|
||||
'jenis' => $jenis,
|
||||
'jkn' => $jkn,
|
||||
'umm' => $umm,
|
||||
'gcu' => $gcu,
|
||||
'tag' => $tag,
|
||||
'swasta' => $swasta,
|
||||
'billing' => $bill,
|
||||
'ele' => $ele,
|
||||
'cito' => $cito,
|
||||
'asuransi' => $asuransi,
|
||||
'nofoto' => $result->nofoto,
|
||||
'noregister' => $result->noregister,
|
||||
'nmpasien' => $nmpasien,
|
||||
'usia' => $result->usia,
|
||||
'kesimpulan' => $result->kesimpulan,
|
||||
'ruangan' => $result->ruangan,
|
||||
'daftar' => $result->daftar,
|
||||
'created_at' => $result->created_at,
|
||||
'nmdokter' => $result->nmdokter,
|
||||
'nmppdssenior' => $result->nmppdssenior,
|
||||
'nmmiddleppds' => $result->nmmiddleppds,
|
||||
'nmppdsjunior' => $result->nmppdsjunior,
|
||||
'nmppdsmiddle2' => $result->nmppdsmiddle2,
|
||||
'nmppdsjunior2' => $result->nmppdsjunior2,
|
||||
'diagnosa2' => $result->diagnosa2,
|
||||
'nmanalis' => $result->nmanalis,
|
||||
'nmexcutor' => $result->nmexcutor,
|
||||
'alamatpasien' => $result->alamatpasien,
|
||||
'tgllahirpasien'=> $tgl,
|
||||
'jkpasien' => $jk,
|
||||
'tlppasien' => $tlppasien,
|
||||
'modality' => $result->modality,
|
||||
'dlp' => $result->dlp,
|
||||
'kd_spesimen' => $result->kd_spesimen,
|
||||
'nm_spesimen' => $result->nm_spesimen,
|
||||
'status' => $result->status,
|
||||
'asalpasien' => $result->asalpasien,
|
||||
'nmrs' => $result->nmrs,
|
||||
'berat' => $result->berat,
|
||||
'klinisi' => $result->klinisi,
|
||||
'klinis' => $result->klinis,
|
||||
'telpon' => $tlppasien,
|
||||
'verifikasi' => $result->verifikasi,
|
||||
'noloket' => $result->noloket,
|
||||
'foto' => $result->foto,
|
||||
'export' => $result->export,
|
||||
'nmdrafter' => $result->nmdrafter,
|
||||
'tgldraft' => $result->tgldraft,
|
||||
'baca' => $result->baca,
|
||||
'nmpembaca' => $result->nmpembaca,
|
||||
'tgladendum' => $result->tgladendum,
|
||||
'nmadendum' => $result->nmadendum,
|
||||
'durasi' => $durasi,
|
||||
];
|
||||
}
|
||||
protected static function getTotalRow($totals) {
|
||||
return [
|
||||
'id' => '',
|
||||
'filefoto' => '',
|
||||
'noregister'=> '',
|
||||
'nama' => '<strong>Total</strong>',
|
||||
'l' => $totals['m'],
|
||||
'p' => $totals['f'],
|
||||
'jkn' => $totals['jkn'],
|
||||
'umm' => $totals['umum'],
|
||||
'gcu' => $totals['gcu'],
|
||||
'tag' => $totals['tag'],
|
||||
'swasta' => $totals['swasta'],
|
||||
'billing' => $totals['bill'],
|
||||
'ele' => $totals['electiv'],
|
||||
'cito' => $totals['cito'],
|
||||
];
|
||||
}
|
||||
public function report(Request $request) {
|
||||
$bulan = $request->input('bulan');
|
||||
$tahun = $request->input('tahun');
|
||||
$homebase = url("/");
|
||||
$arraylist = [];
|
||||
$limit = $request->input('limit') ?? 500;
|
||||
$page = $request->input('pagenum') ?? 1;
|
||||
$order = $request->input('order') ?? 'id desc';
|
||||
$filterscount = $request->input('filterscount') ?? 0;
|
||||
if ($bulan === 'pertanggal' || $bulan === 'terjadwal') {
|
||||
$results = DB::table($bulan === 'terjadwal' ? 'jadwalperiksan' : 'periksa')->when($bulan === 'terjadwal', function ($query) use ($tahun) {
|
||||
return $query->whereNull('jadwalperiksan.status')
|
||||
->where('jadwalperiksan.daftar', 'LIKE', "%$tahun%");
|
||||
}, function ($query) use ($tahun) {
|
||||
return $query->where('periksa.daftar', 'LIKE', "$tahun%");
|
||||
})->get();
|
||||
$totals = ['m' => 0, 'f' => 0, 'jkn' => 0, 'umum' => 0, 'tag' => 0, 'gcu' => 0, 'bill' => 0, 'swasta' => 0, 'electiv' => 0, 'cito' => 0];
|
||||
foreach ($results as $result) {
|
||||
$asuransi = $result->asuransi;
|
||||
$urgensi = $result->urgensi;
|
||||
$totals = self::updateTotals($totals, $asuransi, $urgensi, $result->jkpasien);
|
||||
$arraylist[] = self::mapResultToArray($result);
|
||||
}
|
||||
if ($bulan === 'pertanggal') {
|
||||
$arraylist[] = self::getTotalRow($totals);
|
||||
}
|
||||
echo json_encode($arraylist);
|
||||
} else {
|
||||
if ($bulan == 'ALL' || $bulan == 'Pick Month') {
|
||||
$results = DB::table('periksa')->where('daftar', 'LIKE', $tahun.'%')->get();
|
||||
} else {
|
||||
$tglcari = $tahun.'-'.$bulan;
|
||||
$results = DB::table('periksa')->where('daftar', 'LIKE', $tglcari.'%')->get();
|
||||
}
|
||||
$totals = ['m' => 0, 'f' => 0, 'jkn' => 0, 'umum' => 0, 'tag' => 0, 'gcu' => 0, 'bill' => 0, 'swasta' => 0, 'electiv' => 0, 'cito' => 0];
|
||||
foreach ($results as $result) {
|
||||
$asuransi = $result->asuransi;
|
||||
$urgensi = $result->urgensi;
|
||||
$totals = self::updateTotals($totals, $asuransi, $urgensi, $result->jkpasien);
|
||||
$arraylist[] = self::mapResultToArray($result);
|
||||
}
|
||||
$arraylist[] = self::getTotalRow($totals);
|
||||
echo json_encode($arraylist);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,300 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use App\Jawaban;
|
||||
use App\Subjawaban;
|
||||
use App\SiraB;
|
||||
use App\Organisms;
|
||||
|
||||
use Validator;
|
||||
use Picqer\Barcode\BarcodeGeneratorPNG;
|
||||
use Session;
|
||||
|
||||
class TemplateController extends Controller
|
||||
{
|
||||
public function index() {
|
||||
if (Session::get('previlage') == ''){
|
||||
return redirect('/login');
|
||||
} else {
|
||||
$data = [];
|
||||
return view('admin.template', $data);
|
||||
}
|
||||
}
|
||||
public function viewSIRAb() {
|
||||
$previlage = Session('previlage');
|
||||
if ($previlage == 'developer' OR $previlage == 'supervisor') {
|
||||
$data = [];
|
||||
return view('admin.sirab', $data);
|
||||
} else {
|
||||
$data = [];
|
||||
$data['kalimatheader'] = 'Access Denied';
|
||||
$data['kalimatbody'] = 'Laman khusus SPV';
|
||||
return view('errors.error', $data);
|
||||
}
|
||||
}
|
||||
public function backup() {
|
||||
$previlage = Session('previlage');
|
||||
if ($previlage == 'developer' OR $previlage == 'supervisor') {
|
||||
$data = [];
|
||||
$data['alldata'] = Storage::allFiles('/usr/share/nginx/html/rispacs/public/backupdata');
|
||||
return view('backup', $data);
|
||||
} else {
|
||||
$data = [];
|
||||
$data['kalimatheader'] = 'Access Denied';
|
||||
$data['kalimatbody'] = 'Laman khusus SPV';
|
||||
return view('errors.error', $data);
|
||||
}
|
||||
}
|
||||
public function getListJawaban() {
|
||||
$results = DB::table('jawaban')->get();
|
||||
$arraylist = [];
|
||||
$arraylist[]= array(
|
||||
'id' => 'new',
|
||||
'jawaban' => '<span class="badge badge-primary">Add New</span>'
|
||||
);
|
||||
foreach ($results as $result) {
|
||||
$arraylist[] = array(
|
||||
'id' => $result->id,
|
||||
'jawaban' => $result->jawaban,
|
||||
);
|
||||
}
|
||||
|
||||
echo json_encode($arraylist);
|
||||
}
|
||||
public function updateJawaban(Request $request) {
|
||||
$validator = Validator::make($request->all(), [
|
||||
'val01' => 'required',
|
||||
'val02' => 'required'
|
||||
]);
|
||||
|
||||
if($validator->fails()) {
|
||||
return response()->json(['status' => 'error', 'message' => 'Please fill input field or fill with right input']);
|
||||
} else {
|
||||
$id = $request->input('val02');
|
||||
if ($id != 'new'){
|
||||
Jawaban::where('id', $id)->update(['jawaban' => $request->input('val01')]);
|
||||
}
|
||||
else {
|
||||
Jawaban::create(['jawaban' => $request->input('val01')]);
|
||||
}
|
||||
return response()->json(['status' => 'Success !!', 'message' => 'Category Saved..!!']);
|
||||
}
|
||||
}
|
||||
public function deleteJawaban(Request $request) {
|
||||
try {
|
||||
$id = $request->id;
|
||||
if ($id == 'sirab'){
|
||||
$data = SiraB::find($request->idsirab);
|
||||
} else if ($id == 'mikroorganisme'){
|
||||
$data = Organisms::find($request->idsirab);
|
||||
} else {
|
||||
$data = Jawaban::find($id);
|
||||
}
|
||||
$data->delete();
|
||||
if ($data){
|
||||
return response()->json(['icon' => 'success', 'warna' => '#5ba035', 'status' => 'Success', 'message' => 'Deleted']);
|
||||
return back();
|
||||
} else {
|
||||
return response()->json(['icon' => 'error', 'warna' => '#bf441d', 'status' => 'Failed', 'message' => 'Unkown Error']);
|
||||
return back();
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
return response()->json(['icon' => 'error', 'warna' => '#bf441d', 'status' => 'Failed', 'message' => $e->getMessage()]);
|
||||
return back();
|
||||
}
|
||||
|
||||
}
|
||||
public function getListSubjawaban(Request $request) {
|
||||
$idkat = $request->input('val01');
|
||||
$kategori = $request->input('val02');
|
||||
if ($idkat == 'new') {
|
||||
$arraylist = [];
|
||||
$arraylist[]= array(
|
||||
'id' => 'gakboleh',
|
||||
'kategori' => '-',
|
||||
'judul' => '<span class="badge badge-danger">Please Select Category First</span>',
|
||||
'isine' => '-',
|
||||
'kesimpulan'=> '-'
|
||||
);
|
||||
} else {
|
||||
$arraylist = [];
|
||||
$arraylist[]= array(
|
||||
'id' => 'new',
|
||||
'kategori' => '-',
|
||||
'judul' => '<span class="badge badge-custom">Add New Expertise Themplate</span>',
|
||||
'isine' => '-',
|
||||
'kesimpulan'=> '-'
|
||||
);
|
||||
$results = Subjawaban::where('kategori', $idkat)->get();
|
||||
|
||||
foreach ($results as $result) {
|
||||
$isine = $result->subjawaban;
|
||||
$kesimpulan = $result->kesimpulan;
|
||||
$isine = $isine.' '.$kesimpulan;
|
||||
$arraylist[] = array(
|
||||
'id' => $result->id,
|
||||
'kategori' => $kategori,
|
||||
'judul' => $result->judul,
|
||||
'isine' => $isine,
|
||||
'kesimpulan'=> ''
|
||||
);
|
||||
}
|
||||
}
|
||||
echo json_encode($arraylist);
|
||||
}
|
||||
public function updateSubjawaban(Request $request) {
|
||||
$validator = Validator::make($request->all(), [
|
||||
'val01' => 'required',
|
||||
'val02' => 'required',
|
||||
'val03' => 'required',
|
||||
'val04' => 'required'
|
||||
]);
|
||||
if($validator->fails()) {
|
||||
return response()->json(['status' => 'Error !!', 'message' => 'Please fill input field or fill with right input']);
|
||||
} else {
|
||||
$id = $request->input('val02');
|
||||
if ($id != 'new'){
|
||||
Subjawaban::where('id', $id)->update([
|
||||
'judul' => $request->input('val03'),
|
||||
'subjawaban'=> $request->input('val04'),
|
||||
'kesimpulan'=> ''
|
||||
]);
|
||||
}
|
||||
else {
|
||||
Subjawaban::create([
|
||||
'kategori' => $request->input('val01'),
|
||||
'judul' => $request->input('val03'),
|
||||
'subjawaban'=> $request->input('val04'),
|
||||
'kesimpulan'=> ''
|
||||
]);
|
||||
}
|
||||
return response()->json(['status' => 'Success !!', 'message' => 'Template Saved..!!']);
|
||||
|
||||
}
|
||||
}
|
||||
public function deleteSubjawaban(Request $request) {
|
||||
$id = $request->id;
|
||||
$subjawaban = Subjawaban::find($id);
|
||||
|
||||
$subjawaban->delete();
|
||||
|
||||
return back();
|
||||
}
|
||||
public function showImage($imageName){
|
||||
// Menentukan path gambar di storage
|
||||
$filePath = public_path("{$imageName}");
|
||||
|
||||
// Cek apakah file ada
|
||||
if (!file_exists($filePath)) {
|
||||
abort(404); // Jika file tidak ditemukan, tampilkan error 404
|
||||
}
|
||||
|
||||
// Ambil konten file gambar
|
||||
$imageContent = file_get_contents($filePath);
|
||||
|
||||
// Tentukan MIME type untuk gambar PNG
|
||||
$mimeType = mime_content_type($filePath);
|
||||
|
||||
// Kirim gambar sebagai response dengan header untuk mencegah cache
|
||||
return response($imageContent, 200)
|
||||
->header('Content-Type', $mimeType) // Tentukan MIME type gambar
|
||||
->header('Cache-Control', 'no-store, no-cache, must-revalidate') // Tidak cache di browser
|
||||
->header('Pragma', 'no-cache') // Tidak menggunakan cache pada browser lama
|
||||
->header('Expires', '0'); // Jangan pernah kadaluarsa
|
||||
}
|
||||
public function exUploadKOP(Request $request) {
|
||||
if($request->hasFile('file')) {
|
||||
$ImageExt = $request->file('file')->getClientOriginalExtension();
|
||||
$file_tmp = $request->file('file');
|
||||
$data = file_get_contents($file_tmp);
|
||||
if ($ImageExt == 'png'){
|
||||
try {
|
||||
$unggah = Storage::disk('langsungpublic')->put('kopsurat.png', $data);
|
||||
|
||||
if ($unggah){
|
||||
return response()->json(['icon' => 'success', 'warna' => '#5ba035', 'status' => 'Success', 'message' => 'Pictures Saved, please refresh to apply the change']);
|
||||
return back();
|
||||
} else {
|
||||
return response()->json(['icon' => 'error', 'warna' => '#bf441d', 'status' => 'Failed', 'message' => 'Unkown Error']);
|
||||
return back();
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
return response()->json(['icon' => 'error', 'warna' => '#bf441d', 'status' => 'Failed', 'message' => $e->getMessage()]);
|
||||
return back();
|
||||
}
|
||||
} else {
|
||||
return response()->json(['icon' => 'error', 'warna' => '#bf441d', 'status' => 'Failed', 'message' => 'Only Accept PNG File']);
|
||||
return back();
|
||||
}
|
||||
} else {
|
||||
return response()->json(['icon' => 'error', 'warna' => '#bf441d', 'status' => 'Failed', 'message' => 'No File Selected']);
|
||||
return back();
|
||||
}
|
||||
}
|
||||
public function showBarcode($nofoto){
|
||||
$generator = new BarcodeGeneratorPNG();
|
||||
$barcodeImage = $generator->getBarcode($nofoto, $generator::TYPE_CODE_128);
|
||||
return response($barcodeImage, 200)->header('Content-Type', 'image/png');
|
||||
}
|
||||
public function exSIRAb(Request $request) {
|
||||
try {
|
||||
$id = $request->id;
|
||||
$tabel = $request->tabel;
|
||||
$pesan = 'Unkown Error';
|
||||
if ($tabel == 'Organisme'){
|
||||
if ($id == 'new'){
|
||||
$ceksudah = Organisms::where('name', $request->name)->where('category', $request->category)->where('kelompok', $request->kelompok)->count();
|
||||
if ($ceksudah == 0){
|
||||
$data = new Organisms;
|
||||
$inputData = $request->except(['id', 'tabel', '_token']);
|
||||
$data->fill($inputData);
|
||||
$data->save();
|
||||
} else {
|
||||
$pesan = $request->name.' ('.$request->category.') Sudah ada, Mohon ubah Data sebelum simpan kembali';
|
||||
}
|
||||
} else {
|
||||
$ceksudah = Organisms::where('id', '!=', $id)->where('name', $request->name)->where('category', $request->category)->where('kelompok', $request->kelompok)->count();
|
||||
if ($ceksudah == 0){
|
||||
$data = Organisms::find($id);
|
||||
$inputData = $request->except(['id', 'tabel', '_token']);
|
||||
$data->update($inputData);
|
||||
} else {
|
||||
$pesan = $request->name.' ('.$request->category.') Sudah ada, Mohon ubah Data sebelum simpan kembali';
|
||||
}
|
||||
}
|
||||
if ($data){
|
||||
return response()->json(['icon' => 'success', 'warna' => '#5ba035', 'status' => 'Success', 'message' => 'Saved']);
|
||||
return back();
|
||||
} else {
|
||||
return response()->json(['icon' => 'error', 'warna' => '#bf441d', 'status' => 'Failed', 'message' => 'Unkown Error']);
|
||||
return back();
|
||||
}
|
||||
} else {
|
||||
if ($id == 'new'){
|
||||
$data = new SiraB;
|
||||
$inputData = $request->except(['id', 'tabel', '_token']);
|
||||
$data->fill($inputData);
|
||||
$data->save();
|
||||
} else {
|
||||
$data = SiraB::find($id);
|
||||
$inputData = $request->except(['id', 'tabel', '_token']);
|
||||
$data->update($inputData);
|
||||
}
|
||||
if ($data){
|
||||
return response()->json(['icon' => 'success', 'warna' => '#5ba035', 'status' => 'Success', 'message' => 'Saved']);
|
||||
return back();
|
||||
} else {
|
||||
return response()->json(['icon' => 'error', 'warna' => '#bf441d', 'status' => 'Failed', 'message' => 'Unkown Error']);
|
||||
return back();
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
return response()->json(['icon' => 'error', 'warna' => '#bf441d', 'status' => 'Failed', 'message' => $e->getMessage()]);
|
||||
return back();
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
-16
@@ -19,24 +19,21 @@ class UserController extends Controller
|
||||
if (Session::get('previlage') == ''){
|
||||
return redirect('/login');
|
||||
} else {
|
||||
if ($cekkelompok == 'supervisor' OR $cekkelompok == 'developer'){
|
||||
$getsetting = Setting::where('id', '1')->first();
|
||||
$data = [];
|
||||
$data['users'] = User::orderBy('nama', 'ASC')->get();
|
||||
$data['pacsaddr'] = $getsetting->pacs ?? '';
|
||||
$data['zfpaddr'] = $getsetting->zfp ?? '';
|
||||
$data['port'] = $getsetting->port ?? '';
|
||||
$data['portzfp'] = $getsetting->portzfp ?? '';
|
||||
$data['username'] = $getsetting->username ?? '';
|
||||
$data['password'] = $getsetting->password ?? '';
|
||||
return view('admin.user', $data);
|
||||
if ($cekkelompok == 'supervisor' OR $cekkelompok == 'admin' OR $cekkelompok == 'developer'){
|
||||
$users = User::all();
|
||||
} else {
|
||||
$data = [];
|
||||
$data['kalimatheader'] = 'Access Denied';
|
||||
$data['kalimatbody'] = 'Laman khusus SPV';
|
||||
return view('errors.error', $data);
|
||||
$users = User::where('previlage', $cekkelompok)->get();
|
||||
}
|
||||
|
||||
$getsetting = Setting::where('id', '1')->first();
|
||||
$data = [];
|
||||
$data['users'] = $users;
|
||||
$data['pacsaddr'] = $getsetting->pacs ?? '';
|
||||
$data['zfpaddr'] = $getsetting->zfp ?? '';
|
||||
$data['port'] = $getsetting->port ?? '';
|
||||
$data['portzfp'] = $getsetting->portzfp ?? '';
|
||||
$data['username'] = $getsetting->username ?? '';
|
||||
$data['password'] = $getsetting->password ?? '';
|
||||
return view('admin.user', $data);
|
||||
}
|
||||
}
|
||||
public function exSetting(Request $request) {
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
|
||||
|
||||
class VerifyCsrfToken extends Middleware
|
||||
{
|
||||
/**
|
||||
* The URIs that should be excluded from CSRF verification.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $except = [
|
||||
'registerpasien', 'registerjson', 'ekstrakhasil', 'prosesbatal'
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Periksa extends Model
|
||||
{
|
||||
protected $table = "periksa";
|
||||
protected $guarded = [];
|
||||
public function getMiddlePpdskedua()
|
||||
{
|
||||
return $this->hasOne('App\Models\User','id','middleppds2');
|
||||
}
|
||||
public function getJuniorPpdskedua()
|
||||
{
|
||||
return $this->hasOne('App\Models\User','id','ppdsjunior2');
|
||||
}
|
||||
public function getNmRadiografer()
|
||||
{
|
||||
return $this->hasOne('App\Models\User','id','radiografer');
|
||||
}
|
||||
public function getNmExcutor()
|
||||
{
|
||||
return $this->hasOne('App\Models\User','id','excutor');
|
||||
}
|
||||
public function getNmDokter()
|
||||
{
|
||||
return $this->hasOne('App\Models\User','id','dokter_id');
|
||||
}
|
||||
public function getNmPPDSSenior()
|
||||
{
|
||||
return $this->hasOne('App\Models\User','id','ppdssenior');
|
||||
}
|
||||
public function getPasien()
|
||||
{
|
||||
return $this->hasOne('App\Pasien','id','pasien_id');
|
||||
}
|
||||
public function getPoli()
|
||||
{
|
||||
return $this->hasOne('App\Poli','id','poli_id');
|
||||
}
|
||||
public function getRuangan()
|
||||
{
|
||||
return $this->hasOne('App\Ruangan','id','ruangan_id');
|
||||
}
|
||||
public function getTandatangan()
|
||||
{
|
||||
return $this->hasOne('App\XFiles','xmarking','tandatangan');
|
||||
}
|
||||
public function getLogbook()
|
||||
{
|
||||
return $this->hasOne('App\Logbook','id','diagnosa');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Poli extends Model
|
||||
{
|
||||
protected $table = "poli";
|
||||
protected $fillable = [
|
||||
'poli',
|
||||
'subpoli',
|
||||
'subsubpoli',
|
||||
'modaliti',
|
||||
'modaliti2',
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Cache\RateLimiting\Limit;
|
||||
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\RateLimiter;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
class RouteServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* The path to your application's "home" route.
|
||||
*
|
||||
* Typically, users are redirected here after authentication.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public const HOME = '/home';
|
||||
|
||||
/**
|
||||
* Define your route model bindings, pattern filters, and other route configuration.
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
RateLimiter::for('api', function (Request $request) {
|
||||
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
|
||||
});
|
||||
|
||||
$this->routes(function () {
|
||||
Route::middleware('api')
|
||||
->prefix('api')
|
||||
->group(base_path('routes/api.php'));
|
||||
|
||||
Route::middleware('web')
|
||||
->group(base_path('routes/web.php'));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,555 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use App\ResultSample;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Exception;
|
||||
use App\DataListiner;
|
||||
|
||||
// Proses untuk Growth and Detection Result
|
||||
function processGrowthDetectionResult($rawData){
|
||||
// Format: R|1| ^ ^ ^GND_MGIT^430100001234|INST_POSITIVE ^87| ...
|
||||
$resultData = explode('|', $rawData);
|
||||
|
||||
return [
|
||||
'test_type' => 'Growth/Detection',
|
||||
'accession_number' => $resultData[2],
|
||||
'status' => $resultData[3], // Positif atau Negatif
|
||||
'completion_time' => $resultData[7]
|
||||
];
|
||||
}
|
||||
// Proses untuk Isolate Result
|
||||
function processIsolateResult($rawData){
|
||||
$resultData = explode('|', $rawData);
|
||||
return [
|
||||
'test_type' => 'Isolate',
|
||||
'isolate_result' => $resultData[3],
|
||||
'antibiotic' => $resultData[4],
|
||||
'value' => $resultData[5],
|
||||
'status' => $resultData[6],
|
||||
'completion_time' => $resultData[10]
|
||||
];
|
||||
}
|
||||
// Proses untuk Other Test Result
|
||||
function processOtherResult($rawData){
|
||||
// Format: R|1| ^ ^ ^OTHER^Seq123|Complete| ...
|
||||
$resultData = explode('|', $rawData);
|
||||
|
||||
return [
|
||||
'test_type' => 'Other',
|
||||
'sequence_number' => $resultData[3],
|
||||
'result' => $resultData[4],
|
||||
'description' => $resultData[5],
|
||||
'completion_time' => $resultData[6]
|
||||
];
|
||||
}
|
||||
|
||||
class AstmMessageService
|
||||
{
|
||||
/**
|
||||
* Membersihkan string dari karakter non-printable
|
||||
*/
|
||||
private function cleanString($string)
|
||||
{
|
||||
return preg_replace('/[^\P{C}\n]+/u', '', $string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parsing data berdasarkan format yang diberikan
|
||||
*/
|
||||
private function parseResultData($rawData, $format)
|
||||
{
|
||||
$resultData = explode('|', $rawData);
|
||||
$parsedData = [];
|
||||
|
||||
foreach ($format as $key => $index) {
|
||||
$parsedData[$key] = $resultData[$index] ?? null;
|
||||
}
|
||||
|
||||
return $parsedData;
|
||||
}
|
||||
/**
|
||||
* Proses hasil AST Record
|
||||
*/
|
||||
public function processAstResult($rawData)
|
||||
{
|
||||
$format = [
|
||||
'test_type' => 0,
|
||||
'accession_number' => 2,
|
||||
'antibiotic' => 3,
|
||||
'susceptibility' => 4,
|
||||
'value' => 5,
|
||||
'status' => 6,
|
||||
'completion_time' => 10
|
||||
];
|
||||
|
||||
return $this->parseResultData($rawData, $format);
|
||||
}
|
||||
/**
|
||||
* Proses hasil ID Record
|
||||
*/
|
||||
public function processIdResult($rawData)
|
||||
{
|
||||
$format = [
|
||||
'test_type' => 0,
|
||||
'accession_number' => 2,
|
||||
'organism_name' => 3,
|
||||
'status' => 6,
|
||||
'completion_time' => 10
|
||||
];
|
||||
|
||||
return $this->parseResultData($rawData, $format);
|
||||
}
|
||||
public function createHeader($senderName, $versionNumber)
|
||||
{
|
||||
$messageDateTime = Carbon::now()->format('YmdHis');
|
||||
return "H|{$senderName}|{$versionNumber}|{$messageDateTime}";
|
||||
}
|
||||
|
||||
// Fungsi untuk membuat Patient Record (P)
|
||||
public function createPatientRecord($patient)
|
||||
{
|
||||
// Extract fields from $patient array, adjust field positions based on mapping
|
||||
return "P|{$patient['id']}|{$patient['last_name']}|{$patient['first_name']}|{$patient['middle_name']}|{$patient['suffix']}|{$patient['dob']}|{$patient['sex']}|{$patient['address']}||{$patient['phone']}|{$patient['admitting_physician']}";
|
||||
}
|
||||
|
||||
// Fungsi untuk membuat Order Record (O)
|
||||
public function createOrderRecord($order)
|
||||
{
|
||||
// Order fields based on mapping (Accession Number, Test ID, etc.)
|
||||
return "O|{$order['accession_number']}|{$order['isolate_number']}|{$order['organism']}|{$order['exclude_isolate']}|{$order['priority']}|{$order['collection_date_time']}|{$order['collected_by']}|{$order['received_by']}|{$order['specimen_action_code']}|{$order['isolate_source_test']}|{$order['isolate_source_test_start_time']}|{$order['receipt_date_time']}|{$order['specimen_type']}|{$order['body_site']}|{$order['ordering_physician']}|{$order['ordering_physician_phone']}|{$order['ordering_physician_fax']}|{$order['ordering_physician_pager']}|{$order['specimen_user_field_1']}|{$order['specimen_user_field_2']}|{$order['specimen_user_field_3']}|{$order['specimen_user_field_4']}|{$order['specimen_user_field_5']}|{$order['finalized_date_time']}|{$order['specimen_reimbursement_value']}|{$order['test_reimbursement_value']}|{$order['isolate_classification']}"; }
|
||||
public function createTerminatorRecord($order)
|
||||
{
|
||||
// Order fields based on mapping (Accession Number, Test ID, etc.)
|
||||
return "L|1|N";
|
||||
}
|
||||
// Fungsi untuk membuat pesan lengkap (header + patient + order)
|
||||
public function createMessage($senderName, $versionNumber, $patient, $order)
|
||||
{
|
||||
$header = $this->createHeader($senderName, $versionNumber);
|
||||
$patientRecord = $this->createPatientRecord($patient);
|
||||
$orderRecord = $this->createOrderRecord($order);
|
||||
$terimatorRecord= $this->createTerminatorRecord($order);
|
||||
return implode("\n", [$header, $patientRecord, $orderRecord, $terimatorRecord]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Proses data ASTM Response
|
||||
*/
|
||||
public function processAstmResponse($response, $alat) {
|
||||
// Bersihkan data
|
||||
$astmData = $this->cleanString($response);
|
||||
// Validasi awal: response tidak kosong
|
||||
if (empty($astmData)) {
|
||||
Log::error("ASTM data kosong atau tidak valid.");
|
||||
}
|
||||
$headerData = [];
|
||||
$patientData = [];
|
||||
$orderData = [];
|
||||
$resultData = [];
|
||||
$instrumenDT = [];
|
||||
$mltrData = [];
|
||||
$isolate = null;
|
||||
$accession_number = null;
|
||||
$segments = explode("\n", $astmData);
|
||||
foreach ($segments as $rsegmen){
|
||||
$cekdata = explode('|', $rsegmen);
|
||||
$datapertama = $cekdata[0];
|
||||
$cleankode = preg_replace("/[^a-zA-Z]/", "", $datapertama);
|
||||
if ($cleankode == 'H'){
|
||||
$headerData = array_merge([$cleankode], array_slice($cekdata, 1));
|
||||
}
|
||||
if ($cleankode == 'P'){
|
||||
$patientData = array_merge([$cleankode], array_slice($cekdata, 1));
|
||||
}
|
||||
if ($cleankode == 'O'){
|
||||
$orderData = array_merge([$cleankode], array_slice($cekdata, 1));
|
||||
}
|
||||
if ($cleankode == 'R'){
|
||||
$resultData = array_merge([$cleankode], array_slice($cekdata, 1));
|
||||
}
|
||||
if ($cleankode == 'I'){
|
||||
$instrumenDT = array_merge([$cleankode], array_slice($cekdata, 1));
|
||||
}
|
||||
if ($cleankode == 'mtrsl'){
|
||||
$mltrData = array_merge([$cleankode], array_slice($cekdata, 1));
|
||||
}
|
||||
}
|
||||
if (!empty($patientData) && !empty($headerData)) {
|
||||
$resultSample = new ResultSample();
|
||||
$noregister = $patientData[4] ?? null;
|
||||
$resultSample->sender_name = $alat;
|
||||
$resultSample->version_number = $headerData[11] ?? $patientData[12] ?? null;
|
||||
$resultSample->message_datetime = $resultData[13] ?? null; // '20241130152734'
|
||||
// Patient Record (Segment P)
|
||||
$resultSample->patient_id = $patientData[4] ?? null; // '11607396'
|
||||
$resultSample->patient_name_last = $patientData[6] ?? null; // 'ZAKIYATUN'
|
||||
$resultSample->patient_name_first = $patientData[7] ?? null; // 'O'
|
||||
$resultSample->patient_name_middle = $patientData[8] ?? null;
|
||||
$resultSample->patient_name_suffix = $patientData[9] ?? null;
|
||||
$resultSample->patient_name_title = $patientData[10] ?? null;
|
||||
$resultSample->patient_dob = $resultData[11] ?? null; // '19800101'
|
||||
$resultSample->patient_sex = $patientData[12] ?? null; // 'F'
|
||||
$resultSample->address_street = $patientData[13] ?? null; // 'Street ABC'
|
||||
$resultSample->address_city = $patientData[14] ?? null;
|
||||
$resultSample->address_state = $patientData[15] ?? null;
|
||||
$resultSample->address_zip = $patientData[16] ?? null;
|
||||
$resultSample->address_country = $patientData[17] ?? null;
|
||||
$resultSample->patient_phone = $patientData[18] ?? null; // '081234567890'
|
||||
|
||||
// Order Record (Segment O)
|
||||
$resultSample->accession_number = $orderData[4] ?? null; // '12345'
|
||||
$resultSample->isolate_number = $orderData[5] ?? null; // '67890'
|
||||
$resultSample->organism = $orderData[6] ?? null; // 'E. coli'
|
||||
$resultSample->exclude_isolate_from_statistics = $isolate; // 'false'
|
||||
$resultSample->test_id = $orderData[8] ?? null; // 'Test123'
|
||||
|
||||
// Result Record (Segment R)
|
||||
$resultSample->result_type_code = $resultData[4] ?? null; // 'S'
|
||||
$resultSample->antibiotic = $resultData[5] ?? null; // 'Amoxicillin'
|
||||
$resultSample->antibiotic_concentration = $resultData[6] ?? null; // '100mg'
|
||||
$resultSample->antibiotic_concentration_units = $resultData[7] ?? null; // 'mg'
|
||||
$resultSample->test_status = $resultData[8] ?? null; // 'Completed'
|
||||
$resultSample->result_data = json_encode(array_slice($resultData, 9)); // Additional data (if any)
|
||||
|
||||
$resultSample->preliminary_final_status = $resultData[13] ?? null;
|
||||
$resultSample->test_start_datetime = $resultData[14] ?? null;
|
||||
$resultSample->result_status_datetime = $resultData[15] ?? null;
|
||||
$resultSample->test_complete_datetime = $resultData[16] ?? null;
|
||||
// Periksa apakah data duplikat berdasarkan accession_number
|
||||
//if (ResultSample::where('accession_number', $resultSample->accession_number)->exists()) {
|
||||
// return response()->json(['message' => 'Data sudah ada.'], 409);
|
||||
//}
|
||||
|
||||
// Simpan ke database
|
||||
if ($noregister){
|
||||
Log::info("Data berhasil disimpan:", $resultSample->toArray());
|
||||
$resultSample->save();
|
||||
}
|
||||
return response()->json(['message' => 'Data berhasil diproses dan disimpan.']);
|
||||
|
||||
} else {
|
||||
if (!empty($mltrData)){
|
||||
Log::info("Trying parser MTRSL :", $mltrData);
|
||||
$parsedData = [];
|
||||
$parsedData['antibiotics'] = [];
|
||||
$antibiotic = '';
|
||||
$resistance = '';
|
||||
$value = '';
|
||||
$interpretation = '';
|
||||
$mulaikirim = 0;
|
||||
$resultSample = new ResultSample();
|
||||
foreach ($mltrData as $index => $field) {
|
||||
if ($field == 'ra'){
|
||||
if ($antibiotic != ''){
|
||||
$parsedData['antibiotics'][] = [
|
||||
'antibiotic' => $antibiotic, // Antibiotik
|
||||
'resistance' => $resistance, // Hasil Resistansi
|
||||
'value' => $value, // Nilai
|
||||
'interpretation'=> $interpretation // Interpretasi
|
||||
];
|
||||
$antibiotic = '';
|
||||
$resistance = '';
|
||||
$value = '';
|
||||
$interpretation = '';
|
||||
} else {
|
||||
$mulaikirim = 1;
|
||||
}
|
||||
} else {
|
||||
if ($mulaikirim == 1){
|
||||
$antibiotic = substr($field, 2);
|
||||
$mulaikirim++;
|
||||
} else if ($mulaikirim == 2){
|
||||
$resistance = substr($field, 2);
|
||||
$mulaikirim++;
|
||||
} else if ($mulaikirim == 3){
|
||||
$value = substr($field, 2);
|
||||
$mulaikirim++;
|
||||
} else if ($mulaikirim == 4){
|
||||
$interpretation = substr($field, 2);
|
||||
$mulaikirim++;
|
||||
} else {
|
||||
$field = substr($field, 2);
|
||||
switch ($index) {
|
||||
case 0:
|
||||
$resultSample->sender_name = $alat;
|
||||
break;
|
||||
case 1:
|
||||
$resultSample->version_number = $field; // iiV2
|
||||
break;
|
||||
case 2:
|
||||
$resultSample->isolate_number = $field; // is000015F278BD
|
||||
break;
|
||||
case 4:
|
||||
$resultSample->patient_id = $field; // pi12009427
|
||||
break;
|
||||
case 5:
|
||||
$patientNames = explode(',', $field ?? null);
|
||||
if (count($patientNames) > 0) {
|
||||
$resultSample->patient_name_last = trim($patientNames[0]); // Last name
|
||||
}
|
||||
if (count($patientNames) > 1) {
|
||||
$resultSample->patient_name_first = trim($patientNames[1]); // First name
|
||||
}
|
||||
if (count($patientNames) > 2) {
|
||||
$resultSample->patient_name_middle = trim($patientNames[2]); // Middle name
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
$resultSample->address_street = $field; // plMANINJAU
|
||||
break;
|
||||
case 12:
|
||||
try {
|
||||
$resultSample->message_datetime = Carbon::parse($field)->format('Y-m-d') ?? null;
|
||||
}catch (Exception $e) {
|
||||
$resultSample->message_datetime = date('Y-m-d');
|
||||
}
|
||||
break;
|
||||
case 13:
|
||||
try {
|
||||
$resultSample->test_complete_datetime = Carbon::parse($field)->format('Y-m-d') ?? null;
|
||||
}catch (Exception $e) {
|
||||
$resultSample->test_complete_datetime = date('Y-m-d');
|
||||
}
|
||||
break;
|
||||
case 14:
|
||||
$resultSample->accession_number = substr($field, 6); // ci30112024.26859
|
||||
break;
|
||||
case 23:
|
||||
$resultSample->organism = $field; // o2Staphylococcus haemolyticus
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//$resultSample->specimen_type = $parsedData['specimen_type'] ?? null; // Could be inferred
|
||||
//$resultSample->test_id = $parsedData['test_id'] ?? null;
|
||||
|
||||
// Result Record
|
||||
|
||||
$resultSample->additional_result = json_encode($parsedData['antibiotics']);
|
||||
|
||||
// Menyimpan data yang sudah diparse
|
||||
$resultSample->save();
|
||||
Log::info("Data MTRL Berhasil di Parse dan di simpan ", $resultSample->toArray());
|
||||
return response()->json(['message' => 'Data berhasil diproses dan disimpan.']);
|
||||
} else {
|
||||
$headerData = explode("|", $response);
|
||||
if (isset($headerData[3])){
|
||||
$accnumber = $headerData[47] ?? null;
|
||||
$noregister = $headerData[16] ?? null;
|
||||
$nama = $headerData[18] ?? null;
|
||||
$urgensi = $headerData[50] ?? null; //A Critical R Normal
|
||||
$iddokter = $headerData[33] ?? null;
|
||||
$test_start_datetime = $headerData[52] ?? null;
|
||||
$result_status_datetime = $headerData[59] ?? null;
|
||||
$specimen_type = $headerData[60] ?? null;
|
||||
$resulttype = $headerData[34] ?? null;
|
||||
$resultstatus = $headerData[63] ?? null;
|
||||
$preliminary = $headerData[40] ?? null; //P
|
||||
$test_complete_datetime = $headerData[44] ?? null;
|
||||
$tesid = $headerData[62] ?? null;
|
||||
$alamat = $headerData[23] ?? null;
|
||||
$instrumen = $resultData[2] ?? null;
|
||||
$body_site = '';
|
||||
$tengah = '';
|
||||
$depan = '';
|
||||
$akhir = '';
|
||||
$suffix = '';
|
||||
$title = '';
|
||||
$concentration_unit = '';
|
||||
$kode = '';
|
||||
$antibiotic = '';
|
||||
$city = '';
|
||||
$state = '';
|
||||
$zipcode = '';
|
||||
$country = '';
|
||||
if ($resulttype){
|
||||
$getdataresult = explode('^', $resulttype);
|
||||
$kode = $getdataresult[3] ?? '';
|
||||
$concentration_unit = $getdataresult[4] ?? '';
|
||||
}
|
||||
if ($specimen_type){
|
||||
$getdata = explode('\n', $specimen_type);
|
||||
$specimen_type = $getdata[0];
|
||||
$body_site = $getdata[1] ?? '';
|
||||
}
|
||||
if ($tesid){
|
||||
$gettgl = explode('^', $tesid);
|
||||
$tesid = $gettgl[3] ?? null;
|
||||
}
|
||||
if ($instrumen){
|
||||
$gettgl = explode('^', $instrumen);
|
||||
$instrumen = $gettgl[0];
|
||||
$media_assay_type = $gettgl[1] ?? null;
|
||||
$protocol_length = $gettgl[2] ?? null;
|
||||
$instrument_number = $gettgl[3] ?? null;
|
||||
$instrument_location = $gettgl[4] ?? null;
|
||||
$protocol_name = $gettgl[5] ?? null;
|
||||
} else {
|
||||
$media_assay_type = null;
|
||||
$protocol_length = null;
|
||||
$instrument_number = null;
|
||||
$instrument_location = null;
|
||||
$protocol_name = null;
|
||||
}
|
||||
if ($isolate == '' OR $isolate == '0' OR is_null($isolate)){
|
||||
$isolate = false;
|
||||
} else { $isolate = true; }
|
||||
if ($test_complete_datetime){
|
||||
$test_complete_datetime = substr($test_complete_datetime, 0, 14);
|
||||
//$test_complete_datetime = Carbon::parse($test_complete_datetime)->format('Y-m-d H:i:s');
|
||||
}
|
||||
if ($result_status_datetime){
|
||||
$result_status_datetime = substr($result_status_datetime, 0, 14);
|
||||
//$result_status_datetime = Carbon::parse($result_status_datetime)->format('Y-m-d H:i:s');
|
||||
}
|
||||
if ($test_start_datetime){
|
||||
$test_start_datetime = substr($test_start_datetime, 0, 14);
|
||||
//$test_start_datetime = Carbon::parse($test_start_datetime)->format('Y-m-d H:i:s');
|
||||
}
|
||||
if ($nama){
|
||||
$getnama = explode('\015', $nama);
|
||||
$nama = $getnama[0];
|
||||
$getnama = explode('\n', $nama);
|
||||
$nama = $getnama[0];
|
||||
|
||||
$akhir = $getnama[1] ?? '';
|
||||
$depan = $getnama[2] ?? '';
|
||||
$tengah = $getnama[3] ?? '';
|
||||
$suffix = $getnama[4] ?? '';
|
||||
$title = $getnama[5] ?? '';
|
||||
|
||||
$nama = $nama.$akhir;
|
||||
}
|
||||
if ($alamat){
|
||||
$getnama = explode('^', $alamat);
|
||||
$alamat = $getnama[0];
|
||||
$city = $getnama[1] ?? '';
|
||||
$state = $getnama[2] ?? '';
|
||||
$zipcode = $getnama[3] ?? '';
|
||||
$country = $getnama[4] ?? '';
|
||||
}
|
||||
if ($test_start_datetime == ''){ $test_start_datetime = null; }
|
||||
if ($result_status_datetime == ''){ $result_status_datetime = null; }
|
||||
if ($test_complete_datetime == ''){ $test_complete_datetime = null; }
|
||||
|
||||
$resultSample->sender_name = $headerData[4] ?? 'Unkown';
|
||||
$resultSample->version_number = $headerData[12] ?? 'V0.0';
|
||||
$resultSample->message_datetime = $test_start_datetime;
|
||||
// Patient Record (Segment P)
|
||||
$resultSample->patient_id = $noregister; // '11607396'
|
||||
$resultSample->patient_name_last = $nama; // 'ZAKIYATUN'
|
||||
$resultSample->patient_name_first = $depan; // 'O'
|
||||
$resultSample->patient_name_middle = $tengah;
|
||||
$resultSample->patient_name_suffix = $suffix;
|
||||
$resultSample->patient_name_title = $title;
|
||||
$resultSample->patient_dob = $headerData[20] ?? null;
|
||||
$resultSample->patient_sex = $headerData[21] ?? null;
|
||||
$resultSample->address_street = $alamat;
|
||||
$resultSample->address_city = $city;
|
||||
$resultSample->address_state = $state;
|
||||
$resultSample->address_zip = $zipcode;
|
||||
$resultSample->address_country = $country;
|
||||
$resultSample->patient_phone = $headerData[25] ?? null;
|
||||
$resultSample->admitting_physician = $headerData[27] ?? null;
|
||||
$resultSample->patient_diagnosis = $headerData[33] ?? null;
|
||||
$resultSample->patient_therapy = json_encode($headerData);
|
||||
$resultSample->admit_datetime = null;
|
||||
$resultSample->room_number = $headerData[46] ?? '00001';
|
||||
$resultSample->hospital_service = $headerData[45] ?? 'RSSA Malang';
|
||||
$resultSample->hospital_client = $orderData[4] ?? 'Lab Mikro';
|
||||
|
||||
// Order Record (Segment O)
|
||||
$resultSample->accession_number = $accnumber; // '12345'
|
||||
$resultSample->isolate_number = $orderData[5] ?? null; // '67890'
|
||||
$resultSample->organism = $orderData[6] ?? null; // 'E. coli'
|
||||
$resultSample->exclude_isolate_from_statistics = $isolate; // 'false'
|
||||
$resultSample->specimen_type = $specimen_type;
|
||||
$resultSample->body_site = $body_site;
|
||||
$resultSample->test_id = $tesid; // 'Test123'
|
||||
$resultSample->urgensi = $urgensi; //A Critical R Normal
|
||||
|
||||
// Result Record (Segment R)
|
||||
$resultSample->result_type_code = $kode;
|
||||
$resultSample->antibiotic = $antibiotic;
|
||||
$resultSample->antibiotic_concentration = $concentration_unit; // '100mg'
|
||||
$resultSample->antibiotic_concentration_units = $concentration_unit; // 'mg'
|
||||
$resultSample->test_status = $resultstatus; // 'Completed'
|
||||
$resultSample->result_data = json_encode($orderData); // Additional data (if any)
|
||||
|
||||
$resultSample->preliminary_final_status = $preliminary;
|
||||
$resultSample->test_start_datetime = $test_start_datetime;
|
||||
$resultSample->result_status_datetime = $result_status_datetime;
|
||||
$resultSample->test_complete_datetime = $test_complete_datetime;
|
||||
|
||||
$resultSample->instrument_type = $instrumen;
|
||||
$resultSample->media_assay_type = $media_assay_type;
|
||||
$resultSample->protocol_length = $protocol_length;
|
||||
$resultSample->instrument_number = $instrument_number;
|
||||
$resultSample->instrument_location = $instrument_location;
|
||||
$resultSample->protocol_name = $protocol_name;
|
||||
$resultSample->additional_result = json_encode($resultData);
|
||||
if ($noregister){
|
||||
$resultSample->save();
|
||||
Log::info("Data ASTM Berhasil di Parse dan di simpan ", $resultSample->toArray());
|
||||
return response()->json(['message' => 'Data berhasil diproses dan disimpan.']);
|
||||
}
|
||||
} else {
|
||||
Log::debug("Abaikan Data Berikut ". json_encode($headerData));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Proses data ASTM Response
|
||||
*/
|
||||
public function processAstmMessages($dataListener) {
|
||||
foreach ($dataListener as $data) {
|
||||
try {
|
||||
// Ambil pesan ASTM dari kolom 'message' atau yang relevan
|
||||
$response = $data->rawdt;
|
||||
if ($data->alat == 'BD Mikro 1'){
|
||||
if ($data->no_id != ''){
|
||||
$rnmpas = $data->rnmpas;
|
||||
$getnama = explode('|', $rnmpas);
|
||||
$resultSample = new ResultSample();
|
||||
$resultSample->sender_name = $data->alat;
|
||||
$resultSample->message_datetime = $data->tgl_data;
|
||||
$resultSample->version_number = 'V1.0';
|
||||
$resultSample->patient_id = $data->urut;
|
||||
$resultSample->patient_name_last= $getnama[0];
|
||||
$resultSample->accession_number = $data->no_id;
|
||||
$resultSample->test_status = $data->organisme;
|
||||
$resultSample->save();
|
||||
DataListiner::where('urut', $data->urut)->update([
|
||||
'processed' => 1
|
||||
]);
|
||||
Log::info("Data ASTM BD ", $resultSample->toArray());
|
||||
|
||||
} else {
|
||||
DataListiner::where('urut', $data->urut)->update([
|
||||
'processed' => 9
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
// Lakukan parsing menggunakan method/fungsi yang sudah dibuat
|
||||
$result = $this->processAstmResponse($response, $data->alat);
|
||||
// Jika berhasil, tandai data sudah diproses
|
||||
if ($result) {
|
||||
DataListiner::where('urut', $data->urut)->update([
|
||||
'processed' => 1
|
||||
]);
|
||||
} else {
|
||||
Log::debug($result);
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
Log::critical($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable → Regular
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"name": "laravel/laravel",
|
||||
"type": "project",
|
||||
"description": "The skeleton application for the Laravel framework.",
|
||||
"keywords": ["laravel", "framework"],
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^8.1",
|
||||
"aamdsam/bridging-bpjs": "^1.11",
|
||||
"aranyasen/hl7": "^3.1",
|
||||
"arcanedev/log-viewer": "^10.1",
|
||||
"elibyy/tcpdf-laravel": "^11.1",
|
||||
"fawno/php-serial": "^2.0",
|
||||
"guzzlehttp/guzzle": "^7.8",
|
||||
"laravel/framework": "^10.10",
|
||||
"laravel/passport": "^11.10",
|
||||
"laravel/sanctum": "^3.3",
|
||||
"laravel/tinker": "^2.8",
|
||||
"munafio/chatify": "^1.6",
|
||||
"onecentlin/laravel-adminer": "^7.0",
|
||||
"phpoffice/phpspreadsheet": "^3.3",
|
||||
"picqer/php-barcode-generator": "^3.2",
|
||||
"pusher/pusher-php-server": "^7.2",
|
||||
"setasign/fpdi": "^2.6",
|
||||
"simplesoftwareio/simple-qrcode": "^4.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"fakerphp/faker": "^1.9.1",
|
||||
"laravel/pint": "^1.0",
|
||||
"laravel/sail": "^1.18",
|
||||
"mockery/mockery": "^1.4.4",
|
||||
"nunomaduro/collision": "^7.0",
|
||||
"phpunit/phpunit": "^10.1",
|
||||
"spatie/laravel-ignition": "^2.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"App\\": "app/",
|
||||
"Database\\Factories\\": "database/factories/",
|
||||
"Database\\Seeders\\": "database/seeders/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Tests\\": "tests/"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"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"
|
||||
]
|
||||
},
|
||||
"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
|
||||
}
|
||||
Generated
+10483
File diff suppressed because it is too large
Load diff
@@ -70,7 +70,7 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'timezone' => 'Asia/Jakarta',
|
||||
'timezone' => 'UTC',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@@ -182,7 +182,7 @@ return [
|
||||
*/
|
||||
|
||||
'aliases' => Facade::defaultAliases()->merge([
|
||||
'PDFCREATOR' => Elibyy\TCPDF\Facades\TCPDF::class,
|
||||
// 'Example' => App\Facades\Example::class,
|
||||
])->toArray(),
|
||||
|
||||
];
|
||||
@@ -58,6 +58,9 @@ return [
|
||||
'prefix_indexes'=> true,
|
||||
'strict' => false,
|
||||
'engine' => null,
|
||||
'options' => extension_loaded('pdo_mysql') ? array_filter([
|
||||
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
|
||||
]) : [],
|
||||
],
|
||||
|
||||
'pgsql' => [
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
return [
|
||||
'Title' => 'LIS',
|
||||
'namaapps' => 'Laboratory Information System',
|
||||
'domainapps' => 'RSUD Dr. Saiful Anwar',
|
||||
'subdomainapps' => 'Kota Malang',
|
||||
'subsubdomainapps' => 'Jawa Timur',
|
||||
'addressapps' => 'Jl. Lamandau 18A Bunulrejo Blimbing Malang',
|
||||
'kota' => 'Lumajang',
|
||||
'emailapps' => '[email protected]',
|
||||
'lamanapps' => 'https://lis.swandhana.test',
|
||||
'logofrontapps' => 'header.png',
|
||||
];
|
||||
?>
|
||||
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
|
||||
use Arcanedev\LogViewer\Contracts\Utilities\Filesystem;
|
||||
|
||||
return [
|
||||
|
||||
/* -----------------------------------------------------------------
|
||||
| Log files storage path
|
||||
| -----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
'storage-path' => storage_path('logs'),
|
||||
|
||||
/* -----------------------------------------------------------------
|
||||
| Log files pattern
|
||||
| -----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
'pattern' => [
|
||||
'prefix' => Filesystem::PATTERN_PREFIX, // 'laravel-'
|
||||
'date' => Filesystem::PATTERN_DATE, // '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]'
|
||||
'extension' => Filesystem::PATTERN_EXTENSION, // '.log'
|
||||
],
|
||||
|
||||
/* -----------------------------------------------------------------
|
||||
| Locale
|
||||
| -----------------------------------------------------------------
|
||||
| Supported locales :
|
||||
| 'auto', 'ar', 'bg', 'de', 'en', 'es', 'et', 'fa', 'fr', 'hu', 'hy', 'id', 'it', 'ja', 'ko', 'nl',
|
||||
| 'pl', 'pt-BR', 'ro', 'ru', 'sv', 'th', 'tr', 'zh-TW', 'zh'
|
||||
*/
|
||||
|
||||
'locale' => 'auto',
|
||||
|
||||
/* -----------------------------------------------------------------
|
||||
| Theme
|
||||
| -----------------------------------------------------------------
|
||||
| Supported themes :
|
||||
| 'bootstrap-5'
|
||||
| 'bootstrap-4'
|
||||
| 'bootstrap-3'
|
||||
|
|
||||
| You can make your own theme by adding a folder to the views directory and specifying it here.
|
||||
*/
|
||||
|
||||
'theme' => 'bootstrap-5',
|
||||
|
||||
/* -----------------------------------------------------------------
|
||||
| Route settings
|
||||
| -----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
'route' => [
|
||||
'enabled' => true,
|
||||
|
||||
'attributes' => [
|
||||
'prefix' => 'log-viewer',
|
||||
|
||||
'middleware' => env('ARCANEDEV_LOGVIEWER_MIDDLEWARE') ? explode(',', env('ARCANEDEV_LOGVIEWER_MIDDLEWARE')) : null,
|
||||
],
|
||||
|
||||
'show' => 'log-viewer::logs.show'
|
||||
],
|
||||
|
||||
/* -----------------------------------------------------------------
|
||||
| Log entries per page
|
||||
| -----------------------------------------------------------------
|
||||
| This defines how many logs & entries are displayed per page.
|
||||
*/
|
||||
|
||||
'per-page' => 30,
|
||||
|
||||
/* -----------------------------------------------------------------
|
||||
| Download settings
|
||||
| -----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
'download' => [
|
||||
'prefix' => 'laravel-',
|
||||
|
||||
'extension' => 'log',
|
||||
],
|
||||
|
||||
/* -----------------------------------------------------------------
|
||||
| Menu settings
|
||||
| -----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
'menu' => [
|
||||
'filter-route' => 'log-viewer::logs.filter',
|
||||
|
||||
'icons-enabled' => true,
|
||||
],
|
||||
|
||||
/* -----------------------------------------------------------------
|
||||
| Icons
|
||||
| -----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
'icons' => [
|
||||
/**
|
||||
* Font awesome >= 4.3
|
||||
* http://fontawesome.io/icons/
|
||||
*/
|
||||
'all' => 'fa fa-fw fa-list', // http://fontawesome.io/icon/list/
|
||||
'emergency' => 'fa fa-fw fa-bug', // http://fontawesome.io/icon/bug/
|
||||
'alert' => 'fa fa-fw fa-bullhorn', // http://fontawesome.io/icon/bullhorn/
|
||||
'critical' => 'fa fa-fw fa-heartbeat', // http://fontawesome.io/icon/heartbeat/
|
||||
'error' => 'fa fa-fw fa-times-circle', // http://fontawesome.io/icon/times-circle/
|
||||
'warning' => 'fa fa-fw fa-exclamation-triangle', // http://fontawesome.io/icon/exclamation-triangle/
|
||||
'notice' => 'fa fa-fw fa-exclamation-circle', // http://fontawesome.io/icon/exclamation-circle/
|
||||
'info' => 'fa fa-fw fa-info-circle', // http://fontawesome.io/icon/info-circle/
|
||||
'debug' => 'fa fa-fw fa-life-ring', // http://fontawesome.io/icon/life-ring/
|
||||
],
|
||||
|
||||
/* -----------------------------------------------------------------
|
||||
| Colors
|
||||
| -----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
'colors' => [
|
||||
'levels' => [
|
||||
'empty' => '#D1D1D1',
|
||||
'all' => '#8A8A8A',
|
||||
'emergency' => '#B71C1C',
|
||||
'alert' => '#D32F2F',
|
||||
'critical' => '#F44336',
|
||||
'error' => '#FF5722',
|
||||
'warning' => '#FF9100',
|
||||
'notice' => '#4CAF50',
|
||||
'info' => '#1976D2',
|
||||
'debug' => '#90CAF9',
|
||||
],
|
||||
],
|
||||
|
||||
/* -----------------------------------------------------------------
|
||||
| Strings to highlight in stack trace
|
||||
| -----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
'highlight' => [
|
||||
'^#\d+',
|
||||
'^Stack trace:',
|
||||
],
|
||||
|
||||
];
|
||||
Loaded 100 of 15329 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in New Issue
Block a user