Compare commits
10 Commits
78149d338b
...
5db80d5299
| Author | SHA1 | Date | |
|---|---|---|---|
| 5db80d5299 | |||
|
|
c372590e28 | ||
|
|
52969bde9a | ||
|
|
d5a78e5375 | ||
|
|
48a026fa7e | ||
|
|
0b053a99c6 | ||
|
|
b9706a4a64 | ||
|
|
ece9d2037b | ||
|
|
5d1c28ad1e | ||
|
|
e322ebf199 |
13
.github/workflows/maven.yml
vendored
13
.github/workflows/maven.yml
vendored
@ -28,4 +28,15 @@ jobs:
|
||||
distribution: 'temurin'
|
||||
cache: maven
|
||||
- name: Build with Maven
|
||||
run: mvn -B package -DJWT_SECRET=${{ secrets.JWT_SECRET }} --file pom.xml
|
||||
run: mvn -B package -Dspring.profiles.active=test -DJWT_SECRET=${{ secrets.JWT_SECRET }} --file pom.xml
|
||||
|
||||
|
||||
- name: Build & push Docker image
|
||||
uses: mr-smithers-excellent/docker-build-push@v5
|
||||
with:
|
||||
image: mbgama/hospital-management-api
|
||||
tags: latest
|
||||
registry: docker.io
|
||||
dockerfile: Dockerfile
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@ -31,3 +31,5 @@ build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
.env
|
||||
14
Dockerfile
Normal file
14
Dockerfile
Normal file
@ -0,0 +1,14 @@
|
||||
# ใช้ JRE เป็น base image เพื่อลดขนาด image
|
||||
FROM eclipse-temurin:17-jre-jammy
|
||||
|
||||
# กำหนด working directory ภายใน container
|
||||
WORKDIR /app
|
||||
|
||||
# คัดลอก JAR ไฟล์ที่สร้างขึ้นมาแล้ว
|
||||
# โดยต้องปรับชื่อไฟล์ให้ตรงกับชื่อไฟล์ JAR ของคุณ
|
||||
# เช่น ถ้าชื่อไฟล์คือ target/hospital-management-api-1.0.jar
|
||||
# ก็ใช้ COPY target/hospital-management-api-1.0.jar app.jar
|
||||
COPY target/hospital-management-api-1.0.jar app.jar
|
||||
|
||||
# สั่งรันแอปพลิเคชันเมื่อ container ทำงาน
|
||||
ENTRYPOINT ["java", "-jar", "app.jar"]
|
||||
787
README.md
787
README.md
@ -1,557 +1,286 @@
|
||||
# Hospital Management - API Module 
|
||||
# Hospital Management API (Extended Version)
|
||||
|
||||
## About the project
|
||||
Hospital Management API built in Spring Boot
|
||||

|
||||

|
||||
|
||||
### Prerequisites:
|
||||
- Spring Boot 3.2.1
|
||||
- JDK 17
|
||||
- Maven 4.0.0
|
||||
Extended REST API for Hospital Management, built on top of the original project by Mirna Gama. This version includes new features for user management, inventory, and medical records.
|
||||
|
||||
### Features
|
||||
- [X] R1 - Doctor Registration
|
||||
- [X] R2 - List of Doctors
|
||||
- [X] R3 - Doctor Update
|
||||
- [X] R4 - Doctor Exclusion
|
||||
- [X] R5 - Patient Registration
|
||||
- [X] R6 - List of Patients
|
||||
- [X] R7 - Patient Update
|
||||
- [X] R8 - Patient Exclusion
|
||||
- [X] R9 - Consultation Scheduling
|
||||
- [ ] R10 - Consultation Cancellation
|
||||
---
|
||||
|
||||
## API Documentation - /swagger-ui/index.html
|
||||
## ✨ Improvements and New Features
|
||||
|
||||
### authentication
|
||||
### 1. Code Structure and Architecture
|
||||
|
||||
#### POST - [**/api/auth/register**] - Register a new user
|
||||
* **Entity-Driven Design**: The `UserService` and `AuthServiceImpl` have been refactored to handle user data directly as a `User` entity, making the code cleaner and more aligned with standard Spring Boot practices.
|
||||
* **Simplified Registration**: The old `UserDTO` has been replaced with a new `PatientRegistrationDTO`, which combines user and patient information into a single, comprehensive DTO for a smoother registration process.
|
||||
|
||||
- **Body:**
|
||||
```
|
||||
{
|
||||
"login" (string, required),
|
||||
"password" (string, required),
|
||||
}
|
||||
### 2. Endpoint and Data Handling Changes
|
||||
|
||||
* **New Patient Registration Endpoint**: The old endpoint `POST /api/auth/register` has been replaced with `POST /api/auth/register-patient` to more accurately reflect its function.
|
||||
* **Data Integrity Fix**: We fixed a `DataIntegrityViolationException` caused by an overly long `state` value. Test data has been updated to use a 2-character abbreviation (e.g., "CA") to conform to database constraints.
|
||||
|
||||
### 3. Major Test Suite Refinement
|
||||
|
||||
* **Integration Test**: The `AuthenticationControllerTest` has been updated to support the new `PatientRegistrationDTO` and the new `/api/auth/register-patient` endpoint.
|
||||
* **Unit Test**: Resolved a `NullPointerException` in `AuthServiceTest` by ensuring each test case runs independently, without relying on shared static variables.
|
||||
* **Data Cleanup Order**: Fixed a `Referential integrity constraint violation` by adjusting the data cleanup order in `@AfterAll` to ensure patients are deleted before users.
|
||||
|
||||
### 4. Additional Features
|
||||
|
||||
* Refined the user and patient registration flow.
|
||||
* Introduced **RBAC (Role-Based Access Control)** to manage system permissions.
|
||||
* Improved the database schema for better data management.
|
||||
* Added a **Default Admin** user for easier initial setup.
|
||||
|
||||
---
|
||||
|
||||
## 🛠 Tech Stack
|
||||
- Java 17
|
||||
- Spring Boot 3.x
|
||||
- PostgreSQL + pgAdmin (via Docker)
|
||||
- Spring Security (JWT + RBAC)
|
||||
- JUnit 5 & Mockito (Testing)
|
||||
- Swagger / OpenAPI
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Features - v2.0
|
||||
|
||||
### Core Data Management
|
||||
* **`Doctor`**
|
||||
* [x] **R1** - Doctor Registration
|
||||
* [x] **R2** - Doctor List
|
||||
* [x] **R3** - Doctor Data Update
|
||||
* [x] **R4** - Doctor Data Exclusion
|
||||
* **`Patient`**
|
||||
* [x] **R5** - Patient Registration
|
||||
* [x] **R6** - Patient List
|
||||
* [x] **R7** - Patient Data Update
|
||||
* [x] **R8** - Patient Data Exclusion
|
||||
* **`Staff`**
|
||||
* [x] **R9** - Staff Creation
|
||||
* **`Nurse`**
|
||||
* [x] **R10** - Nurse Registration
|
||||
* [x] **R11** - Nurse List
|
||||
* [x] **R12** - Nurse Data Update
|
||||
* [x] **R13** - Nurse Data Exclusion
|
||||
|
||||
### Specialized Management
|
||||
* **`Consultation`**
|
||||
* [x] **R14** - Scheduling a Consultation
|
||||
* [x] **R15** - Canceling a Consultation
|
||||
* [x] **R16** - Viewing an Individual Consultation
|
||||
* **`Doctor Schedule`**
|
||||
* [x] **R17** - Adding a new Doctor Schedule
|
||||
* **`Nurse Schedule`**
|
||||
* [x] **R18** - Adding a new Nurse Schedule
|
||||
* [x] **R19** - Viewing Nurse Schedules (Pagination)
|
||||
* **`Operating Room`**
|
||||
* [x] **R20** - Add / Update / Delete Operating Room
|
||||
* [x] **R21** - View Operating Rooms List
|
||||
* **`Operating Room Schedule`**
|
||||
* [x] **R22** - Add / View Operating Room Schedules
|
||||
* **`Medical Record`**
|
||||
* [x] **R23** - Medical Record Creation
|
||||
* [x] **R24** - Medical Record Update
|
||||
* [x] **R25** - Medical Record Exclusion
|
||||
* [x] **R26** - Viewing a Medical Record by ID
|
||||
* **`Prescription`**
|
||||
* [x] **R27** - New Prescription Creation
|
||||
* **`Medical Image`**
|
||||
* [x] **R28** - Upload / Download Medical Images
|
||||
* **`Lab Result`**
|
||||
* [x] **R29** - Create / View Lab Results by Medical Record ID
|
||||
|
||||
### Inventory Management
|
||||
* **`Inventory Item`**
|
||||
* [x] **R30** - Inventory Item Creation
|
||||
* [x] **R31** - Inventory Item Update
|
||||
* [x] **R32** - Inventory Item Exclusion
|
||||
* [x] **R33** - Viewing an Inventory Item by ID
|
||||
* **`Inventory Transaction`**
|
||||
* [x] **R34** - Inventory Transaction Creation
|
||||
* **`Inventory Supplier`**
|
||||
* [x] **R35** - Supplier Creation
|
||||
* **`Inventory Item Type`**
|
||||
* [x] **R36** - Item Type Creation
|
||||
|
||||
### Insurance Management
|
||||
* **`Insurance Provider`**
|
||||
* [x] **R37** - Provider Creation / Update / Delete
|
||||
* [x] **R38** - Viewing Providers List
|
||||
* **`Insurance Claim`**
|
||||
* [x] **R39** - Claim Creation / Update / Delete
|
||||
* [x] **R40** - Viewing Claims List
|
||||
|
||||
### Billing & Payment
|
||||
* **`Billing`**
|
||||
* [x] **R41** - Billing Record Creation / Update / Delete
|
||||
* [x] **R42** - Viewing Billing by ID
|
||||
* **`Payment`**
|
||||
* [x] **R43** - Payment Record Creation
|
||||
* [x] **R44** - Viewing all Payment Records
|
||||
* [x] **R45** - Viewing an Individual Payment Record
|
||||
|
||||
### Reports
|
||||
* **`Inventory Reports`**
|
||||
* [x] **R46** - Low Stock Report
|
||||
* **`Financial Reports`**
|
||||
* [x] **R47** - Financial Overview Report
|
||||
* **`Appointment Reports`**
|
||||
* [x] **R48** - Appointments Report
|
||||
|
||||
### User Management
|
||||
* [x] **R49** - Update Username
|
||||
* [x] **R50** - Update Password
|
||||
* [x] **R51** - Update Role
|
||||
* [x] **R52** - Deactivate User Account
|
||||
* [x] **R53** - Activate User Account
|
||||
* [x] **R54** - Link Patient to User
|
||||
* [x] **R55** - Register Nurse and Link
|
||||
* [x] **R56** - Register Doctor and Link
|
||||
|
||||
---
|
||||
|
||||
## 🔑 Default Credentials
|
||||
|
||||
For initial administrative access, use the following credentials:
|
||||
|
||||
* **Username:** `admin@softwarecraft.tech`
|
||||
* **Password:** `pasword123`
|
||||
|
||||
---
|
||||
|
||||
## 📖 API Endpoints
|
||||
|
||||
### 🔑 Authentication (`authentication-controller`)
|
||||
* `POST` `/api/auth/register-patient` - Register a new patient
|
||||
* `POST` `/api/auth/register-doctor-and-link` - Register a new doctor and link them to a user account
|
||||
* `POST` `/api/auth/register-staff` - Register a new staff member
|
||||
* `POST` `/api/auth/login` - Log in to the system
|
||||
* `POST` `/api/auth/link-patient-to-user` - Link a patient to an existing user account
|
||||
|
||||
### 👤 User Management (`user-controller`)
|
||||
* `PUT` `/api/v1.0/users/{id}/username` - Update a user's username
|
||||
* `PUT` `/api/v1.0/users/{id}/role` - Update a user's role
|
||||
* `PUT` `/api/v1.0/users/{id}/password` - Update a user's password
|
||||
* `PATCH` `/api/v1.0/users/{id}/deactivate` - Deactivate a user's account
|
||||
* `PATCH` `/api/v1.0/users/{id}/activate` - Activate a user's account
|
||||
|
||||
### 🧑⚕️ Doctors (`doctor-controller`)
|
||||
* `GET` `/api/v1.0/doctors` - Retrieve a list of all doctors
|
||||
* `POST` `/api/v1.0/doctors` - Create a new doctor
|
||||
* `GET` `/api/v1.0/doctors/{id}` - Retrieve a single doctor by ID
|
||||
* `PUT` `/api/v1.0/doctors` - Update an existing doctor
|
||||
* `DELETE` `/api/v1.0/doctors/{id}` - Delete a doctor by ID
|
||||
|
||||
### 🤒 Patients (`patient-controller`)
|
||||
* `GET` `/api/v1.0/patients` - Retrieve a list of all patients
|
||||
* `POST` `/api/v1.0/patients` - Create a new patient
|
||||
* `GET` `/api/v1.0/patients/{id}` - Retrieve a single patient by ID
|
||||
* `PUT` `/api/v1.0/patients` - Update an existing patient
|
||||
* `DELETE` `/api/v1.0/patients/{id}` - Delete a patient by ID
|
||||
|
||||
### 🏥 Staff (`staff-controller`)
|
||||
* `POST` `/api/v1.0/staff` - Add a new staff member
|
||||
|
||||
### 🩺 Consultations (`consultation-controller`)
|
||||
* `POST` `/api/v1.0/consultations` - Create a new consultation
|
||||
* `GET` `/api/v1.0/consultations/{id}` - Retrieve a consultation by ID
|
||||
* `DELETE` `/api/v1.0/consultations` - Cancel a consultation
|
||||
|
||||
### 📆 Doctor Schedules (`doctor-schedules-controller`)
|
||||
* `POST` `/api/v1.0/doctor-schedules` - Add a new doctor schedule
|
||||
|
||||
### 📝 Medical Records (`medical-record-controller`)
|
||||
* `POST` `/api/v1.0/medical-records` - Create a new medical record
|
||||
* `GET` `/api/v1.0/medical-records/{id}` - Retrieve a medical record by ID
|
||||
* `PUT` `/api/v1.0/medical-records/{id}` - Update a medical record
|
||||
* `DELETE` `/api/v1.0/medical-records/{id}` - Delete a medical record
|
||||
|
||||
### 💊 Prescriptions (`prescriptions-controller`)
|
||||
* `POST` `/api/v1.0/prescriptions` - Create a new prescription
|
||||
|
||||
### 💲 Payments (`payment-controller`)
|
||||
* `POST` `/api/v1.0/payments` - Create a new payment record
|
||||
* `GET` `/api/v1.0/payments` - Retrieve all payment records
|
||||
* `GET` `/api/v1.0/payments/{id}` - Retrieve a single payment record by ID
|
||||
|
||||
### 📦 Inventory (`inventory-controller`)
|
||||
* `POST` `/api/v1.0/inventory/items` - Create a new inventory item
|
||||
* `GET` `/api/v1.0/inventory/items/{id}` - Retrieve an inventory item by ID
|
||||
* `PUT` `/api/v1.0/inventory/items/{id}` - Update an inventory item
|
||||
* `DELETE` `/api/v1.0/inventory/items/{id}` - Delete an inventory item
|
||||
* `POST` `/api/v1.0/inventory/transactions` - Create a new inventory transaction
|
||||
* `POST` `/api/v1.0/inventory/suppliers` - Create a new supplier
|
||||
* `POST` `/api/v1.0/inventory/item-types` - Create a new inventory item type
|
||||
|
||||
---
|
||||
|
||||
## 🚀 How to Run
|
||||
|
||||
### 1️⃣ Clone the Repository
|
||||
```bash
|
||||
git clone <this repository>
|
||||
cd hospital-management-api
|
||||
```
|
||||
|
||||
- **Responses:**
|
||||
### 2️⃣ Set Environment Variables for IntelliJ
|
||||
|
||||
| Code | Description |
|
||||
| ------------- | ------------- |
|
||||
| `200` | _Successful operation_ |
|
||||
| `400` | _Validation Error_ |
|
||||
เปิด IntelliJ → ไปที่ Run → Edit Configurations
|
||||
|
||||
#### POST - [**/api/auth/login**] - Perform the login
|
||||
เลือก Configuration ของ Spring Boot ของโปรเจค
|
||||
|
||||
- **Body:**
|
||||
ในส่วน Environment Variables กำหนดค่าตามนี้:
|
||||
```
|
||||
{
|
||||
"login" (string, required),
|
||||
"password" (string, required),
|
||||
}
|
||||
POSTGRES_HOST=localhost
|
||||
POSTGRES_PORT=5432
|
||||
POSTGRES_DB=<your_database_name>
|
||||
POSTGRES_USER=<your_database_user>
|
||||
POSTGRES_PASSWORD=<your_database_password>
|
||||
JWT_SECRET=<your_jwt_secret>
|
||||
MINIO_URL=<your_minio_url>
|
||||
MINIO_ACCESS=<your_minio_access_key>
|
||||
MINIO_SECRET=<your_minio_secret_key>
|
||||
MINIO_BUCKET=<your_minio_bucket>
|
||||
PGADMIN_DEFAULT_EMAIL=<your_pgadmin_email>
|
||||
PGADMIN_DEFAULT_PASSWORD=<your_pgadmin_password>
|
||||
```
|
||||
|
||||
- **Responses:**
|
||||
|
||||
| Code | Description |
|
||||
| ------------- | ------------- |
|
||||
| `200` | _Successful operation_ |
|
||||
| `400` | _Validation Error_ |
|
||||
| `403` | _Incorrect credentials_ |
|
||||
|
||||
|
||||
### doctors
|
||||
|
||||
#### POST - [**/api/v1.0/doctors**] - Adds a new doctor
|
||||
|
||||
- **Body:**
|
||||
### 3️⃣ Run PostgreSQL and pgAdmin
|
||||
```
|
||||
{
|
||||
"name" (string, required),
|
||||
"email" (string, required),
|
||||
"crm" (string, required),
|
||||
"telephone" (string, required),
|
||||
"specialty" (string, required),
|
||||
"address": {
|
||||
"street" (string, required),
|
||||
"neighborhood" (string, required),
|
||||
"zipCode" (string, required),
|
||||
"city" (string, required),
|
||||
"state" (string, required),
|
||||
"additionalDetails" (string, optional),
|
||||
"houseNumber" (string, optional)
|
||||
}
|
||||
}
|
||||
# รันเฉพาะ PostgreSQL และ pgAdmin
|
||||
docker-compose up -d postgresdb pgadmin
|
||||
|
||||
```
|
||||
|
||||
- **Request Headers:**
|
||||
### 4️⃣ Run Spring Boot Application
|
||||
|
||||
| Key | Description |
|
||||
| ------------- | ------------- |
|
||||
| `Authorization` | _Authorization token_ |
|
||||
เปิด IntelliJ
|
||||
|
||||
- **Responses:**
|
||||
Run Spring Boot จาก Configuration ที่ตั้งค่า Environment Variables แล้ว
|
||||
|
||||
| Code | Description |
|
||||
| ------------- | ------------- |
|
||||
| `201` | _Successfully created_ |
|
||||
| `400` | _Validation Error_ |
|
||||
| `403` | _Unauthorized / Invalid token_ |
|
||||
✅ แอปจะเชื่อมต่อ PostgreSQL และ MinIO ตามค่าที่กำหนด
|
||||
|
||||
#### GET - [**/api/v1.0/doctors/{id}**] - Get an existing doctor
|
||||
---
|
||||
|
||||
- **Response Body Example:**
|
||||
```
|
||||
{
|
||||
"id": 1,
|
||||
"name": "DOCTOR TEST",
|
||||
"email": "test@gmail.com",
|
||||
"crm": "12456",
|
||||
"telephone": "(81) 99999999",
|
||||
"specialty": "ORTHOPEDICS",
|
||||
"active": true,
|
||||
"address": {
|
||||
"street": "TEST STR.",
|
||||
"neighborhood": "TEST NEIGHBORHOOD",
|
||||
"zipCode": "12345678",
|
||||
"city": "TEST CITY",
|
||||
"state": "ST",
|
||||
"additionalDetails": null,
|
||||
"houseNumber": null
|
||||
}
|
||||
}
|
||||
```
|
||||
### Future Development Plan (v2.1+)
|
||||
|
||||
- **Request Headers:**
|
||||
We will continue to develop on Spring Boot following standard best practices to add the following capabilities:
|
||||
|
||||
| Key | Description |
|
||||
| ------------- | ------------- |
|
||||
| `Authorization` | _Authorization token_ |
|
||||
**AI-Driven Enhancements**
|
||||
- Implement predictive analytics for patient admissions and resource allocation.
|
||||
- Integrate AI models for anomaly detection in lab results or vital signs.
|
||||
- Use Natural Language Processing (NLP) for automated parsing of medical notes.
|
||||
- Suggest treatment plans or risk alerts based on historical patient data.
|
||||
---
|
||||
|
||||
- **Request Parameters:**
|
||||
## 📝 API Documentation
|
||||
Full API documentation (Swagger UI) is available at:
|
||||
https://his-backend.softwarecraft.tech/swagger-ui/index.html
|
||||
|
||||
| Key | Description |
|
||||
| ------------- | ------------- |
|
||||
| `id` | _Unique identifier of the doctor who will be fetched_ |
|
||||
---
|
||||
|
||||
- **Responses:**
|
||||
|
||||
| Code | Description |
|
||||
| ------------- | ------------- |
|
||||
| `200` | _Successful operation_ |
|
||||
| `404` | _Entity not found_ |
|
||||
| `403` | _Unauthorized / Invalid token_ |
|
||||
|
||||
#### GET - [**/api/v1.0/doctors**] - Get a list of doctors
|
||||
|
||||
- **Response Body Example:**
|
||||
```
|
||||
{
|
||||
"content": [
|
||||
{
|
||||
"name": "Test1",
|
||||
"email": "test1@gmail.com",
|
||||
"crm": "123456",
|
||||
"specialty": "ORTHOPEDICS"
|
||||
},
|
||||
{
|
||||
"name": "Test2",
|
||||
"email": "test2@gmail.com",
|
||||
"crm": "789101",
|
||||
"specialty": "ORTHOPEDICS"
|
||||
},
|
||||
{
|
||||
"name": "Test3",
|
||||
"email": "test3@gmail.com",
|
||||
"crm": "112131",
|
||||
"specialty": "ORTHOPEDICS"
|
||||
},
|
||||
],
|
||||
"pageable": {
|
||||
"pageNumber": 0,
|
||||
"pageSize": 10,
|
||||
"sort": {
|
||||
"sorted": true,
|
||||
"unsorted": false,
|
||||
"empty": false
|
||||
},
|
||||
"offset": 0,
|
||||
"paged": true,
|
||||
"unpaged": false
|
||||
},
|
||||
"totalPages": 1,
|
||||
"totalElements": 3,
|
||||
"last": true,
|
||||
"sort": {
|
||||
"sorted": true,
|
||||
"unsorted": false,
|
||||
"empty": false
|
||||
},
|
||||
"number": 0,
|
||||
"size": 10,
|
||||
"first": true,
|
||||
"numberOfElements": 3,
|
||||
"empty": false
|
||||
}
|
||||
```
|
||||
|
||||
- **Request Headers:**
|
||||
|
||||
| Key | Description |
|
||||
| ------------- | ------------- |
|
||||
| `Authorization` | _Authorization token_ |
|
||||
|
||||
- **Request Parameters:**
|
||||
|
||||
| Key | Description |
|
||||
| ------------- | ------------- |
|
||||
| `size` | _Number of records that should be returned_ |
|
||||
| `sort` | _Sort by object attribute in descending order_ |
|
||||
| `page` | _Page number_ |
|
||||
|
||||
- **Responses:**
|
||||
|
||||
| Code | Description |
|
||||
| ------------- | ------------- |
|
||||
| `200` | _Successful operation_ |
|
||||
| `403` | _Unauthorized / Invalid token_ |
|
||||
|
||||
|
||||
#### PUT - [**/api/v1.0/doctors**] - Updates an existing doctor
|
||||
|
||||
- **Body:**
|
||||
```
|
||||
{
|
||||
"id" (number, required),
|
||||
"name" (string, optional),
|
||||
"telephone" (string, optional),
|
||||
"address": {
|
||||
"street" (string, optional),
|
||||
"neighborhood" (string, optional),
|
||||
"zipcode" (string, optional),
|
||||
"city" (string, optional),
|
||||
"state" (string, optional),
|
||||
"additionalDetails" (string, optional),
|
||||
"houseNumber" (string, optional),
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- **Request Headers:**
|
||||
|
||||
| Key | Description |
|
||||
| ------------- | ------------- |
|
||||
| `Authorization` | _Authorization token_ |
|
||||
|
||||
- **Responses:**
|
||||
|
||||
| Code | Description |
|
||||
| ------------- | ------------- |
|
||||
| `200` | _Successful operation_ |
|
||||
| `400` | _Validation Error_ |
|
||||
| `403` | _Unauthorized / Invalid token_ |
|
||||
|
||||
|
||||
#### DELETE - [**/api/v1.0/doctors/{id}**] - Deactivates an existing doctor
|
||||
|
||||
- **Response Body Example:**
|
||||
```
|
||||
{
|
||||
"id": 2,
|
||||
"name": "DEACTIVATED DOCTOR TEST",
|
||||
"email": "test@gmail.com",
|
||||
"crm": "12456",
|
||||
"telephone": "(81) 99999999",
|
||||
"specialty": "ORTHOPEDICS",
|
||||
"active": false,
|
||||
"address": {
|
||||
"street": "TEST STR.",
|
||||
"neighborhood": "TEST NEIGHBORHOOD",
|
||||
"zipCode": "12345678",
|
||||
"city": "TEST CITY",
|
||||
"state": "ST",
|
||||
"additionalDetails": null,
|
||||
"houseNumber": null
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- **Request Headers:**
|
||||
|
||||
| Key | Description |
|
||||
| ------------- | ------------- |
|
||||
| `Authorization` | _Authorization token_ |
|
||||
|
||||
- **Request Parameters:**
|
||||
|
||||
| Key | Description |
|
||||
| ------------- | ------------- |
|
||||
| `id` | _Unique identifier of the doctor who will be deactivated_ |
|
||||
|
||||
- **Responses:**
|
||||
|
||||
| Code | Description |
|
||||
| ------------- | ------------- |
|
||||
| `200` | _Successful operation_ |
|
||||
| `400` | _Validation Error_ |
|
||||
| `404` | _Entity not found_ |
|
||||
| `403` | _Unauthorized / Invalid token_ |
|
||||
|
||||
### patients
|
||||
|
||||
#### POST - [**/api/v1.0/patients**] - Adds a new patient
|
||||
|
||||
- **Body:**
|
||||
```
|
||||
{
|
||||
"name" (string, required),
|
||||
"email" (string, required),
|
||||
"cpf" (string, required),
|
||||
"telephone" (string, required),
|
||||
"address": {
|
||||
"street" (string, required),
|
||||
"neighborhood" (string, required),
|
||||
"zipCode" (string, required),
|
||||
"city" (string, required),
|
||||
"state" (string, required),
|
||||
"additionalDetails" (string, optional),
|
||||
"houseNumber" (string, optional)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- **Request Headers:**
|
||||
|
||||
| Key | Description |
|
||||
| ------------- | ------------- |
|
||||
| `Authorization` | _Authorization token_ |
|
||||
|
||||
- **Responses:**
|
||||
|
||||
| Code | Description |
|
||||
| ------------- | ------------- |
|
||||
| `201` | _Successfully created_ |
|
||||
| `400` | _Validation Error_ |
|
||||
| `403` | _Unauthorized / Invalid token_ |
|
||||
|
||||
|
||||
#### GET - [**/api/v1.0/patients/{id}**] - Get an existing patient
|
||||
|
||||
- **Response Body Example:**
|
||||
```
|
||||
{
|
||||
"id": 1,
|
||||
"name": "PATIENT TEST",
|
||||
"email": "test@gmail.com",
|
||||
"cpf": "11111111111",
|
||||
"telephone": "(81) 99999999",
|
||||
"active": true,
|
||||
"address": {
|
||||
"street": "TEST STR.",
|
||||
"neighborhood": "TEST NEIGHBORHOOD",
|
||||
"zipCode": "12345678",
|
||||
"city": "TEST CITY",
|
||||
"state": "ST",
|
||||
"additionalDetails": null,
|
||||
"houseNumber": null
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- **Request Headers:**
|
||||
|
||||
| Key | Description |
|
||||
| ------------- | ------------- |
|
||||
| `Authorization` | _Authorization token_ |
|
||||
|
||||
- **Request Parameters:**
|
||||
|
||||
| Key | Description |
|
||||
| ------------- | ------------- |
|
||||
| `id` | _Unique identifier of the patient who will be fetched_ |
|
||||
|
||||
- **Responses:**
|
||||
|
||||
| Code | Description |
|
||||
| ------------- | ------------- |
|
||||
| `200` | _Successful operation_ |
|
||||
| `404` | _Entity not found_ |
|
||||
| `403` | _Unauthorized / Invalid token_ |
|
||||
|
||||
#### GET - [**/api/v1.0/patients**] - Get a list of patients
|
||||
|
||||
- **Response Body Example:**
|
||||
```
|
||||
{
|
||||
"content": [
|
||||
{
|
||||
"name": "Test1",
|
||||
"email": "test1@gmail.com",
|
||||
"cpf": "123456"
|
||||
},
|
||||
{
|
||||
"name": "Test2",
|
||||
"email": "test2@gmail.com",
|
||||
"cpf": "789101"
|
||||
},
|
||||
{
|
||||
"name": "Test3",
|
||||
"email": "test3@gmail.com",
|
||||
"cpf": "112131"
|
||||
},
|
||||
],
|
||||
"pageable": {
|
||||
"pageNumber": 0,
|
||||
"pageSize": 10,
|
||||
"sort": {
|
||||
"sorted": true,
|
||||
"unsorted": false,
|
||||
"empty": false
|
||||
},
|
||||
"offset": 0,
|
||||
"paged": true,
|
||||
"unpaged": false
|
||||
},
|
||||
"totalPages": 1,
|
||||
"totalElements": 3,
|
||||
"last": true,
|
||||
"sort": {
|
||||
"sorted": true,
|
||||
"unsorted": false,
|
||||
"empty": false
|
||||
},
|
||||
"number": 0,
|
||||
"size": 10,
|
||||
"first": true,
|
||||
"numberOfElements": 3,
|
||||
"empty": false
|
||||
}
|
||||
```
|
||||
|
||||
- **Request Headers:**
|
||||
|
||||
| Key | Description |
|
||||
| ------------- | ------------- |
|
||||
| `Authorization` | _Authorization token_ |
|
||||
|
||||
- **Request Parameters:**
|
||||
|
||||
| Key | Description |
|
||||
| ------------- | ------------- |
|
||||
| `size` | _Number of records that should be returned_ |
|
||||
| `sort` | _Sort by object attribute in descending order_ |
|
||||
| `page` | _Page number_ |
|
||||
|
||||
- **Responses:**
|
||||
|
||||
| Code | Description |
|
||||
| ------------- | ------------- |
|
||||
| `200` | _Successful operation_ |
|
||||
| `403` | _Unauthorized / Invalid token_ |
|
||||
|
||||
#### PUT - [**/api/v1.0/patients**] - Updates an existing patient
|
||||
|
||||
- **Body:**
|
||||
```
|
||||
{
|
||||
"id" (number, required),
|
||||
"name" (string, optional),
|
||||
"telephone" (string, optional),
|
||||
"address": {
|
||||
"street" (string, optional),
|
||||
"neighborhood" (string, optional),
|
||||
"zipcode" (string, optional),
|
||||
"city" (string, optional),
|
||||
"state" (string, optional),
|
||||
"additionalDetails" (string, optional),
|
||||
"houseNumber" (string, optional),
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- **Request Headers:**
|
||||
|
||||
| Key | Description |
|
||||
| ------------- | ------------- |
|
||||
| `Authorization` | _Authorization token_ |
|
||||
|
||||
- **Responses:**
|
||||
|
||||
| Code | Description |
|
||||
| ------------- | ------------- |
|
||||
| `200` | _Successful operation_ |
|
||||
| `400` | _Validation Error_ |
|
||||
| `403` | _Unauthorized / Invalid token_ |
|
||||
|
||||
#### DELETE - [**/api/v1.0/patients/{id}**] - Deactivates an existing patient
|
||||
|
||||
- **Response Body Example:**
|
||||
```
|
||||
{
|
||||
"id": 1,
|
||||
"name": "DEACTIVATED PATIENT TEST",
|
||||
"email": "test@gmail.com",
|
||||
"cpf": "11111111111",
|
||||
"telephone": "(81) 99999999",
|
||||
"active": false,
|
||||
"address": {
|
||||
"street": "TEST STR.",
|
||||
"neighborhood": "TEST NEIGHBORHOOD",
|
||||
"zipCode": "12345678",
|
||||
"city": "TEST CITY",
|
||||
"state": "ST",
|
||||
"additionalDetails": null,
|
||||
"houseNumber": null
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- **Request Headers:**
|
||||
|
||||
| Key | Description |
|
||||
| ------------- | ------------- |
|
||||
| `Authorization` | _Authorization token_ |
|
||||
|
||||
- **Request Parameters:**
|
||||
|
||||
| Key | Description |
|
||||
| ------------- | ------------- |
|
||||
| `id` | _Unique identifier of the patient who will be deactivated_ |
|
||||
|
||||
- **Responses:**
|
||||
|
||||
| Code | Description |
|
||||
| ------------- | ------------- |
|
||||
| `200` | _Successful operation_ |
|
||||
| `400` | _Validation Error_ |
|
||||
| `404` | _Entity not found_ |
|
||||
| `403` | _Unauthorized / Invalid token_ |
|
||||
|
||||
### consultations
|
||||
|
||||
#### POST - [**/api/v1.0/consultations**] - Adds a new consultation
|
||||
|
||||
- **Body:**
|
||||
```
|
||||
{
|
||||
"patientId" (number, required),
|
||||
"consultationDate" (string, required),
|
||||
"doctorId" (number, required if _specialty_ field is not filled),
|
||||
"specialty" (string, required if _doctorId_ field is not filled)
|
||||
}
|
||||
```
|
||||
|
||||
- **Request Headers:**
|
||||
|
||||
| Key | Description |
|
||||
| ------------- | ------------- |
|
||||
| `Authorization` | _Authorization token_ |
|
||||
|
||||
- **Responses:**
|
||||
|
||||
| Code | Description |
|
||||
| ------------- | ------------- |
|
||||
| `200` | _Successful operation |
|
||||
| `400` | _Validation Error_ |
|
||||
| `403` | _Unauthorized / Invalid token_ |
|
||||
| `404` | _Entity not found_ |
|
||||
## 🙏 Credits
|
||||
Extended version of MirnaGama/hospital-management-api.
|
||||
This continuation improves code quality, adds features, and addresses real-world issues.
|
||||
51
docker-compose.yml
Normal file
51
docker-compose.yml
Normal file
@ -0,0 +1,51 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
postgresdb:
|
||||
image: postgres:13
|
||||
container_name: postgres-hospital
|
||||
restart: always
|
||||
environment:
|
||||
POSTGRES_USER: ${POSTGRES_USER}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
POSTGRES_DB: ${POSTGRES_DB}
|
||||
ports:
|
||||
- '5432:5432'
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
|
||||
api:
|
||||
image: adminsoftwarecraft/hospital-api:v1.0.0
|
||||
container_name: hospital-api-container
|
||||
restart: on-failure
|
||||
environment:
|
||||
SPRING_DATASOURCE_URL: jdbc:postgresql://postgresdb:5432/${POSTGRES_DB}
|
||||
SPRING_DATASOURCE_USERNAME: ${POSTGRES_USER}
|
||||
SPRING_DATASOURCE_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
JWT_SECRET: ${JWT_SECRET}
|
||||
MINIO_URL: ${MINIO_URL}
|
||||
MINIO_ACCESS: ${MINIO_ACCESS}
|
||||
MINIO_SECRET: ${MINIO_SECRET}
|
||||
MINIO_BUCKET: ${MINIO_BUCKET}
|
||||
ports:
|
||||
- "8080:8080"
|
||||
depends_on:
|
||||
- postgresdb
|
||||
|
||||
pgadmin:
|
||||
image: dpage/pgadmin4
|
||||
container_name: pgadmin-hospital
|
||||
restart: always
|
||||
environment:
|
||||
PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL}
|
||||
PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD}
|
||||
ports:
|
||||
- '8180:80'
|
||||
volumes:
|
||||
- pgadmin-data:/var/lib/pgadmin
|
||||
depends_on:
|
||||
- postgresdb
|
||||
|
||||
volumes:
|
||||
postgres-data:
|
||||
pgadmin-data:
|
||||
39
pom.xml
39
pom.xml
@ -10,7 +10,7 @@
|
||||
</parent>
|
||||
<groupId>com.mirna</groupId>
|
||||
<artifactId>hospital-management-api</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<version>1.0</version>
|
||||
<name>hospital-management-api</name>
|
||||
<description>Hospital Management API project for Spring Boot</description>
|
||||
<properties>
|
||||
@ -40,24 +40,37 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.30</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- PostgreSQL JDBC Driver -->
|
||||
<dependency>
|
||||
<groupId>org.flywaydb</groupId>
|
||||
<artifactId>flyway-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.flywaydb</groupId>
|
||||
<artifactId>flyway-mysql</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Flyway PostgreSQL (optional ตั้งแต่ Flyway 7+ ไม่จำเป็นถ้าใช้ core) -->
|
||||
<dependency>
|
||||
<groupId>org.flywaydb</groupId>
|
||||
<artifactId>flyway-core</artifactId>
|
||||
<version>9.22.3</version>
|
||||
</dependency>
|
||||
|
||||
<!-- MinIO Java Client -->
|
||||
<dependency>
|
||||
<groupId>io.minio</groupId>
|
||||
<artifactId>minio</artifactId>
|
||||
<version>8.5.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>2.1.214</version>
|
||||
<scope>test</scope>
|
||||
<version>2.2.220</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
||||
@ -0,0 +1,49 @@
|
||||
package com.mirna.hospitalmanagementapi.application.controllers;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.Billing;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.BillingDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.BillingService;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
import java.net.URI;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1.0/billings")
|
||||
@SecurityRequirement(name = "bearer-key")
|
||||
public class BillingController {
|
||||
|
||||
@Autowired
|
||||
private BillingService billingService;
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<Billing> createBilling(@RequestBody @Valid BillingDTO billingDTO, UriComponentsBuilder uriBuilder) {
|
||||
Billing newBilling = billingService.createBilling(billingDTO);
|
||||
URI uri = uriBuilder.path("/api/v1.0/billings/{id}").buildAndExpand(newBilling.getId()).toUri();
|
||||
return ResponseEntity.created(uri).body(newBilling);
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@PreAuthorize("hasAnyRole('ADMIN', 'RECEPTIONIST') or (hasRole('PATIENT') and @billingServiceImpl.isOwner(#id, authentication.principal.id))")
|
||||
public ResponseEntity<Billing> getBillingById(@PathVariable Long id) {
|
||||
Billing billing = billingService.getBillingById(id);
|
||||
return ResponseEntity.ok(billing);
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public ResponseEntity<Billing> updateBilling(@PathVariable Long id, @RequestBody @Valid BillingDTO billingDTO) {
|
||||
Billing updatedBilling = billingService.updateBilling(id, billingDTO);
|
||||
return ResponseEntity.ok(updatedBilling);
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public ResponseEntity<Void> deleteBilling(@PathVariable Long id) {
|
||||
billingService.deleteBilling(id);
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
}
|
||||
@ -21,6 +21,10 @@ import com.mirna.hospitalmanagementapi.domain.entities.Consultation;
|
||||
import com.mirna.hospitalmanagementapi.domain.exceptions.ConsultationValidationException;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.ConsultationService;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.ExampleObject;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
@ -35,59 +39,84 @@ import jakarta.validation.Valid;
|
||||
@SecurityRequirement(name = "bearer-key")
|
||||
public class ConsultationController {
|
||||
|
||||
@Autowired
|
||||
private ConsultationService consultationService;
|
||||
@Autowired
|
||||
private ConsultationService consultationService;
|
||||
|
||||
/**
|
||||
* Post method to create a new Consultation object based on the provided DTO.
|
||||
*
|
||||
* @param consultationDTO The data transfer object containing data for Consultation
|
||||
* entity.
|
||||
*
|
||||
* @return A response entity containing the saved consultation and created status if successful, or
|
||||
* a 400-level error if there is a validation error
|
||||
* @throws ConsultationValidationException if there is a validation error
|
||||
*/
|
||||
@PostMapping
|
||||
public ResponseEntity<Object> postConsultation(@RequestBody @Valid ConsultationDTO consultationDTO) throws ConsultationValidationException {
|
||||
Consultation consultation = consultationService.addConsultation(consultationDTO);
|
||||
/**
|
||||
* Post method to create a new Consultation object based on the provided DTO.
|
||||
*
|
||||
* @param consultationDTO The data transfer object containing data for Consultation
|
||||
* entity.
|
||||
* * @return A response entity containing the saved consultation and created status if successful, or
|
||||
* a 400-level error if there is a validation error
|
||||
* @throws ConsultationValidationException if there is a validation error
|
||||
*/
|
||||
@PostMapping
|
||||
@Operation(
|
||||
summary = "สร้างการนัดหมายใหม่",
|
||||
description = "อนุญาตให้ผู้ป่วยจองการนัดหมายกับแพทย์ที่ระบุหรือตามแผนก",
|
||||
requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
|
||||
content = @Content(
|
||||
mediaType = "application/json",
|
||||
examples = {
|
||||
@ExampleObject(
|
||||
name = "ตัวอย่าง: จองด้วยรหัสแพทย์",
|
||||
summary = "จองนัดหมายกับแพทย์ที่ต้องการโดยตรง",
|
||||
value = "{\"doctorId\": 1, \"patientId\": 1, \"consultationDate\": \"2025-09-15T10:00:00+07:00\", \"specialty\": null}"
|
||||
),
|
||||
@ExampleObject(
|
||||
name = "ตัวอย่าง: จองด้วยแผนก",
|
||||
summary = "จองนัดหมายโดยให้ระบบเลือกแพทย์ที่ว่างในแผนกที่ระบุ",
|
||||
value = "{\"doctorId\": null, \"patientId\": 1, \"consultationDate\": \"2025-09-15T11:00:00+07:00\", \"specialty\": \"ORTHOPEDICS\"}"
|
||||
)
|
||||
}
|
||||
)
|
||||
),
|
||||
responses = {
|
||||
@ApiResponse(responseCode = "201", description = "สร้างการนัดหมายสำเร็จ"),
|
||||
@ApiResponse(responseCode = "400", description = "ข้อมูลใน Request Body ไม่ถูกต้อง หรือการตรวจสอบล้มเหลว")
|
||||
}
|
||||
)
|
||||
public ResponseEntity<Object> postConsultation(@RequestBody @Valid ConsultationDTO consultationDTO) throws ConsultationValidationException {
|
||||
System.out.println("--- Inside ConsultationController.postConsultation ---");
|
||||
System.out.println("Received DTO: " + consultationDTO.toString());
|
||||
|
||||
UriComponents uriComponents = UriComponentsBuilder
|
||||
.fromUriString("/api/v1.0/consultations/{id}")
|
||||
.encode()
|
||||
.build();
|
||||
Consultation consultation = consultationService.addConsultation(consultationDTO);
|
||||
|
||||
URI uri = uriComponents.expand(consultation.getId()).toUri();
|
||||
UriComponents uriComponents = UriComponentsBuilder
|
||||
.fromUriString("/api/v1.0/consultations/{id}")
|
||||
.encode()
|
||||
.build();
|
||||
|
||||
return ResponseEntity.created(uri).body(consultation);
|
||||
}
|
||||
URI uri = uriComponents.expand(consultation.getId()).toUri();
|
||||
|
||||
/**
|
||||
* Get method to receive a Consultation record by the provided ID
|
||||
*
|
||||
* @param id A long representing the consultation's unique identifier
|
||||
*
|
||||
* @return A response entity containing the corresponding consultation if successful, or
|
||||
* a 400-level error if it is non-existent
|
||||
*/
|
||||
@GetMapping("/{id}")
|
||||
public ResponseEntity<Object> getConsultation(@PathVariable Long id) {
|
||||
Consultation consultation = consultationService.findConsultationById(id);
|
||||
return ResponseEntity.created(uri).body(consultation);
|
||||
}
|
||||
|
||||
return ResponseEntity.ok(consultation);
|
||||
}
|
||||
/**
|
||||
* Get method to receive a Consultation record by the provided ID
|
||||
*
|
||||
* @param id A long representing the consultation's unique identifier
|
||||
* * @return A response entity containing the corresponding consultation if successful, or
|
||||
* a 400-level error if it is non-existent
|
||||
*/
|
||||
@GetMapping("/{id}")
|
||||
public ResponseEntity<Object> getConsultation(@PathVariable Long id) {
|
||||
Consultation consultation = consultationService.findConsultationById(id);
|
||||
|
||||
/**
|
||||
* Delete method to update a new Consultation object based on the provided DTO.
|
||||
*
|
||||
* @param consultationCanceledDTO The data transfer object containing data to update Consultation
|
||||
* entity.
|
||||
*
|
||||
* @return A response entity containing the canceled consultation and ok status if successful, or
|
||||
* a 400-level error if the consultation entity is not found
|
||||
*/
|
||||
@DeleteMapping
|
||||
public ResponseEntity<Object> deleteConsultation(@RequestBody @Valid ConsultationCanceledDTO consultationCanceledDTO) {
|
||||
return ResponseEntity.ok(consultationService.cancelConsultation(consultationCanceledDTO));
|
||||
}
|
||||
return ResponseEntity.ok(consultation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete method to update a new Consultation object based on the provided DTO.
|
||||
*
|
||||
* @param consultationCanceledDTO The data transfer object containing data to update Consultation
|
||||
* entity.
|
||||
* * @return A response entity containing the canceled consultation and ok status if successful, or
|
||||
* a 400-level error if the consultation entity is not found
|
||||
*/
|
||||
@DeleteMapping
|
||||
public ResponseEntity<Object> deleteConsultation(@RequestBody @Valid ConsultationCanceledDTO consultationCanceledDTO) {
|
||||
return ResponseEntity.ok(consultationService.cancelConsultation(consultationCanceledDTO));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
package com.mirna.hospitalmanagementapi.application.controllers;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.DoctorScheduleDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.Doctor;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.DoctorSchedule;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.DoctorScheduleService;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.DoctorService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* REST controller for doctor schedules.
|
||||
*
|
||||
* @author FlookSP
|
||||
* @version 1.1
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/v1.0/doctor-schedules")
|
||||
@Tag(name = "doctor-dchedule-controller")
|
||||
public class DoctorScheduleController {
|
||||
|
||||
@Autowired
|
||||
private DoctorScheduleService doctorScheduleService;
|
||||
|
||||
@Autowired
|
||||
private DoctorService doctorService; // ใช้สำหรับค้นหา Doctor Entity
|
||||
|
||||
@PostMapping
|
||||
@Operation(summary = "เพิ่มตารางเวลาของแพทย์ใหม่", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<DoctorSchedule> addDoctorSchedule(@RequestBody @Valid DoctorScheduleDTO dto) {
|
||||
|
||||
// 1. ค้นหา Doctor Entity จาก doctorId ใน DTO
|
||||
Doctor doctor = doctorService.findDoctorById(dto.doctorId());
|
||||
if (doctor == null) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
// 2. แปลง DTO เป็น Entity
|
||||
DoctorSchedule doctorSchedule = new DoctorSchedule(
|
||||
doctor,
|
||||
dto.dayOfWeek(),
|
||||
dto.startTime(),
|
||||
dto.endTime()
|
||||
);
|
||||
|
||||
// 3. บันทึก DoctorSchedule
|
||||
DoctorSchedule savedSchedule = doctorScheduleService.saveDoctorSchedule(doctorSchedule);
|
||||
|
||||
return ResponseEntity.ok(savedSchedule);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
package com.mirna.hospitalmanagementapi.application.controllers;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.InsuranceClaim;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.InsuranceClaimDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.InsuranceClaimService;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1.0/insurance-claims")
|
||||
@SecurityRequirement(name = "bearer-key")
|
||||
public class InsuranceClaimController {
|
||||
|
||||
@Autowired
|
||||
private InsuranceClaimService insuranceClaimService;
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<InsuranceClaim> createInsuranceClaim(@RequestBody @Valid InsuranceClaimDTO insuranceClaimDTO, UriComponentsBuilder uriBuilder) {
|
||||
InsuranceClaim newClaim = insuranceClaimService.createInsuranceClaim(insuranceClaimDTO);
|
||||
URI uri = uriBuilder.path("/api/v1.0/insurance-claims/{id}").buildAndExpand(newClaim.getId()).toUri();
|
||||
return ResponseEntity.created(uri).body(newClaim);
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public ResponseEntity<InsuranceClaim> getInsuranceClaimById(@PathVariable Long id) {
|
||||
InsuranceClaim claim = insuranceClaimService.getInsuranceClaimById(id);
|
||||
return ResponseEntity.ok(claim);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public ResponseEntity<Page<InsuranceClaim>> getAllInsuranceClaims(@PageableDefault(size = 10, page = 0, sort = {"id"}) Pageable pageable) {
|
||||
Page<InsuranceClaim> claims = insuranceClaimService.getAllInsuranceClaims(pageable);
|
||||
return ResponseEntity.ok(claims);
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public ResponseEntity<InsuranceClaim> updateInsuranceClaim(@PathVariable Long id, @RequestBody @Valid InsuranceClaimDTO insuranceClaimDTO) {
|
||||
InsuranceClaim updatedClaim = insuranceClaimService.updateInsuranceClaim(id, insuranceClaimDTO);
|
||||
return ResponseEntity.ok(updatedClaim);
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public ResponseEntity<Void> deleteInsuranceClaim(@PathVariable Long id) {
|
||||
insuranceClaimService.deleteInsuranceClaim(id);
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
package com.mirna.hospitalmanagementapi.application.controllers;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.InsuranceProviderDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.InsuranceProvider;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.InsuranceProviderService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1.0/insurance-providers")
|
||||
@Tag(name = "insurance-provider-controller")
|
||||
public class InsuranceProviderController {
|
||||
|
||||
@Autowired
|
||||
private InsuranceProviderService insuranceProviderService;
|
||||
|
||||
@PostMapping
|
||||
@Operation(summary = "เพิ่มผู้ให้บริการประกันรายใหม่เข้าสู่ระบบ", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<InsuranceProvider> addInsuranceProvider(@RequestBody @Valid InsuranceProviderDTO insuranceProviderDTO) {
|
||||
InsuranceProvider newProvider = insuranceProviderService.addInsuranceProvider(insuranceProviderDTO);
|
||||
return new ResponseEntity<>(newProvider, HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@Operation(summary = "ดึงรายการผู้ให้บริการประกันทั้งหมด", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<List<InsuranceProvider>> getAllInsuranceProviders() {
|
||||
List<InsuranceProvider> providers = insuranceProviderService.getAllInsuranceProviders();
|
||||
return ResponseEntity.ok(providers);
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@Operation(summary = "ดึงข้อมูลผู้ให้บริการประกันตามรหัส (ID)", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<InsuranceProvider> getInsuranceProviderById(@PathVariable Long id) throws EntityNotFoundException {
|
||||
InsuranceProvider provider = insuranceProviderService.getInsuranceProviderById(id);
|
||||
return ResponseEntity.ok(provider);
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
@Operation(summary = "อัปเดตข้อมูลผู้ให้บริการประกันที่มีอยู่", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<InsuranceProvider> updateInsuranceProvider(@PathVariable Long id, @RequestBody @Valid InsuranceProviderDTO updatedProviderDTO) throws EntityNotFoundException {
|
||||
InsuranceProvider updatedProvider = insuranceProviderService.updateInsuranceProvider(id, updatedProviderDTO);
|
||||
return ResponseEntity.ok(updatedProvider);
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
@Operation(summary = "ลบผู้ให้บริการประกันออกจากระบบ", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<Void> deleteInsuranceProvider(@PathVariable Long id) throws EntityNotFoundException {
|
||||
insuranceProviderService.deleteInsuranceProvider(id);
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
package com.mirna.hospitalmanagementapi.application.controllers;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.inventory.InventoryItemDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.inventory.InventoryItemResponseDTO; // Import DTO สำหรับ Response
|
||||
import com.mirna.hospitalmanagementapi.domain.services.inventory.InventoryItemService;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import java.util.UUID;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1.0/inventory/items")
|
||||
public class InventoryItemController {
|
||||
|
||||
@Autowired
|
||||
private InventoryItemService inventoryItemService;
|
||||
|
||||
@PostMapping
|
||||
@Operation(summary = "สร้างรายการสินค้าคงคลังใหม่", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<InventoryItemResponseDTO> createInventoryItem(@RequestBody @Valid InventoryItemDTO itemDTO) {
|
||||
InventoryItemResponseDTO newItem = inventoryItemService.addInventoryItem(itemDTO);
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(newItem);
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@Operation(summary = "ดึงข้อมูลรายการสินค้าคงคลังด้วย ID", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<InventoryItemResponseDTO> getInventoryItem(@PathVariable UUID id) {
|
||||
InventoryItemResponseDTO item = inventoryItemService.getInventoryItemById(id);
|
||||
return ResponseEntity.ok(item);
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
@Operation(summary = "อัปเดตข้อมูลรายการสินค้าคงคลัง", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<InventoryItemResponseDTO> updateInventoryItem(@PathVariable UUID id, @RequestBody @Valid InventoryItemDTO itemDTO) {
|
||||
InventoryItemResponseDTO updatedItem = inventoryItemService.updateInventoryItem(id, itemDTO);
|
||||
return ResponseEntity.ok(updatedItem);
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
@Operation(summary = "ลบรายการสินค้าคงคลัง", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<Void> deleteInventoryItem(@PathVariable UUID id) {
|
||||
inventoryItemService.deleteInventoryItem(id);
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package com.mirna.hospitalmanagementapi.application.controllers;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.services.inventory.ItemTypeService;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.inventory.ItemTypeDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.inventory.InventoryItemType;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1.0/inventory/item-types")
|
||||
public class InventoryItemTypeController {
|
||||
|
||||
@Autowired
|
||||
private ItemTypeService itemTypeService;
|
||||
|
||||
@PostMapping
|
||||
@Operation(summary = "สร้างประเภทรายการสินค้าคงคลังใหม่", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<InventoryItemType> createItemType(@RequestBody @Valid ItemTypeDTO itemTypeDTO) {
|
||||
InventoryItemType newItemType = itemTypeService.addItemType(itemTypeDTO);
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(newItemType);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package com.mirna.hospitalmanagementapi.application.controllers;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.services.inventory.SupplierService;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.inventory.SupplierDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.inventory.InventorySupplier;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1.0/inventory/suppliers")
|
||||
public class InventorySupplierController {
|
||||
|
||||
@Autowired
|
||||
private SupplierService supplierService;
|
||||
|
||||
@PostMapping
|
||||
@Operation(summary = "สร้างข้อมูลผู้จำหน่ายสินค้าใหม่", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<InventorySupplier> createSupplier(@RequestBody @Valid SupplierDTO supplierDTO) {
|
||||
InventorySupplier newSupplier = supplierService.addSupplier(supplierDTO);
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(newSupplier);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package com.mirna.hospitalmanagementapi.application.controllers;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.services.inventory.InventoryTransactionService;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.inventory.InventoryTransactionDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.inventory.InventoryTransactionResponseDTO; // Import DTO สำหรับ Response
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1.0/inventory/transactions")
|
||||
public class InventoryTransactionController {
|
||||
|
||||
@Autowired
|
||||
private InventoryTransactionService transactionService;
|
||||
|
||||
@PostMapping
|
||||
@Operation(summary = "สร้างรายการธุรกรรมคงคลังใหม่", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<InventoryTransactionResponseDTO> createTransaction(@RequestBody @Valid InventoryTransactionDTO transactionDTO) {
|
||||
InventoryTransactionResponseDTO newTransaction = transactionService.addTransaction(transactionDTO);
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(newTransaction);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
package com.mirna.hospitalmanagementapi.application.controllers;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.LabResultDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.LabResult;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.LabResultService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import java.util.UUID;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1.0/lab-results")
|
||||
public class LabResultController {
|
||||
|
||||
@Autowired
|
||||
private LabResultService labResultService;
|
||||
|
||||
@PostMapping("/{medicalRecordId}")
|
||||
@Operation(summary = "สร้างผลแล็บใหม่และเชื่อมโยงกับบันทึกทางการแพทย์", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<LabResult> addLabResult(
|
||||
@PathVariable Long medicalRecordId,
|
||||
@RequestBody LabResultDTO labResultDTO) {
|
||||
|
||||
LabResult newLabResult = labResultService.addLabResult(medicalRecordId, labResultDTO);
|
||||
return new ResponseEntity<>(newLabResult, HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@Operation(summary = "ดึงข้อมูลผลแล็บด้วย ID", security = @SecurityRequirement(name = "bearer-key"))
|
||||
@PreAuthorize("hasAnyRole('ADMIN', 'DOCTOR') or (hasRole('PATIENT') and @labResultService.isOwner(#id, authentication.principal.id))")
|
||||
public ResponseEntity<LabResult> getLabResultById(@PathVariable UUID id) {
|
||||
LabResult labResult = labResultService.getLabResultById(id);
|
||||
return ResponseEntity.ok(labResult);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
package com.mirna.hospitalmanagementapi.application.controllers;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.MedicalEquipmentScheduleDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.MedicalEquipmentSchedule;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.MedicalEquipmentScheduleService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.MedicalEquipmentScheduleResponseDTO;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1.0/medical-equipment-schedules")
|
||||
@Tag(name = "medical-equipment-schedule-controller")
|
||||
public class MedicalEquipmentScheduleController {
|
||||
|
||||
@Autowired
|
||||
private MedicalEquipmentScheduleService medicalEquipmentScheduleService;
|
||||
|
||||
@PostMapping
|
||||
@Operation(summary = "เพิ่มตารางเวลาอุปกรณ์ทางการแพทย์ใหม่เข้าสู่ระบบ", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<MedicalEquipmentScheduleResponseDTO> addMedicalEquipmentSchedule(@RequestBody @Valid MedicalEquipmentScheduleDTO medicalEquipmentScheduleDTO, UriComponentsBuilder uriBuilder) {
|
||||
MedicalEquipmentScheduleResponseDTO newSchedule = medicalEquipmentScheduleService.addMedicalEquipmentSchedule(medicalEquipmentScheduleDTO);
|
||||
URI uri = uriBuilder.path("/api/v1.0/medical-equipment-schedules/{id}").buildAndExpand(newSchedule.getId()).toUri();
|
||||
return ResponseEntity.created(uri).body(newSchedule);
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@Operation(summary = "ดึงข้อมูลตารางเวลาอุปกรณ์ทางการแพทย์ตามรหัส (ID)", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<MedicalEquipmentScheduleResponseDTO> getMedicalEquipmentScheduleById(@PathVariable Long id) throws EntityNotFoundException {
|
||||
MedicalEquipmentScheduleResponseDTO schedule = medicalEquipmentScheduleService.getMedicalEquipmentScheduleById(id);
|
||||
return ResponseEntity.ok(schedule);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@Operation(summary = "ดึงข้อมูลตารางเวลาอุปกรณ์ทางการแพทย์ทั้งหมดแบบแบ่งหน้า (Pagination)", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<Page<MedicalEquipmentScheduleResponseDTO>> getAllMedicalEquipmentSchedules(@PageableDefault(size = 10, page = 0, sort = {"startTime"}) Pageable pageable) {
|
||||
Page<MedicalEquipmentScheduleResponseDTO> schedules = medicalEquipmentScheduleService.getAllMedicalEquipmentSchedules(pageable);
|
||||
return ResponseEntity.ok(schedules);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
package com.mirna.hospitalmanagementapi.application.controllers;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.MedicalImage;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.MedicalImageService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import java.util.UUID;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1.0/medical-images")
|
||||
public class MedicalImageController {
|
||||
|
||||
@Autowired
|
||||
private MedicalImageService medicalImageService;
|
||||
|
||||
@PostMapping(value = "/upload/{medicalRecordId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
@Operation(summary = "อัปโหลดรูปภาพและเชื่อมโยงกับบันทึกทางการแพทย์", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<MedicalImage> uploadImage(
|
||||
@PathVariable Long medicalRecordId,
|
||||
@RequestParam("file") MultipartFile file,
|
||||
@RequestParam("imageType") String imageType,
|
||||
@RequestParam("notes") String notes) {
|
||||
|
||||
MedicalImage uploadedImage = medicalImageService.uploadImage(medicalRecordId, file, imageType, notes);
|
||||
return new ResponseEntity<>(uploadedImage, HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
@GetMapping("/download/{id}")
|
||||
@Operation(summary = "ดาวน์โหลดรูปภาพทางการแพทย์ด้วย ID", security = @SecurityRequirement(name = "bearer-key"))
|
||||
@PreAuthorize("hasAnyRole('ADMIN', 'DOCTOR') or (hasRole('PATIENT') and @medicalImageService.isOwner(#id, authentication.principal.id))")
|
||||
public ResponseEntity<Resource> downloadImage(@PathVariable UUID id) {
|
||||
Resource file = medicalImageService.downloadImage(id);
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + id + ".jpg\"")
|
||||
.contentType(MediaType.IMAGE_JPEG) // สามารถเปลี่ยนประเภทไฟล์ตามต้องการ
|
||||
.body(file);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
package com.mirna.hospitalmanagementapi.application.controllers;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.MedicalRecord;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.MedicalRecordService;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.MedicalRecordDTO;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1.0/medical-records")
|
||||
public class MedicalRecordController {
|
||||
|
||||
@Autowired
|
||||
private MedicalRecordService medicalRecordService;
|
||||
|
||||
@PostMapping
|
||||
@Operation(summary = "สร้างบันทึกทางการแพทย์ใหม่", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<MedicalRecord> addMedicalRecord(@RequestBody MedicalRecordDTO medicalRecordDTO) {
|
||||
MedicalRecord newRecord = medicalRecordService.addMedicalRecord(medicalRecordDTO);
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(newRecord);
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@Operation(summary = "ดึงข้อมูลบันทึกทางการแพทย์ด้วย ID (ไม่รวมรายละเอียดเพิ่มเติม)", security = @SecurityRequirement(name = "bearer-key"))
|
||||
@PreAuthorize("hasAnyRole('ADMIN', 'DOCTOR') or (hasRole('PATIENT') and @medicalRecordService.isOwner(#id, authentication.principal.id))")
|
||||
public ResponseEntity<MedicalRecord> getMedicalRecordById(@PathVariable Long id) {
|
||||
MedicalRecord medicalRecord = medicalRecordService.getMedicalRecordById(id);
|
||||
return ResponseEntity.ok(medicalRecord);
|
||||
}
|
||||
|
||||
// Endpoint ใหม่สำหรับดึงข้อมูลบันทึกทางการแพทย์พร้อมรายละเอียดทั้งหมด
|
||||
/*@GetMapping("/{id}/details")
|
||||
@Operation(summary = "ดึงข้อมูลบันทึกทางการแพทย์พร้อมรายละเอียดทั้งหมด", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<MedicalRecord> getMedicalRecordDetails(@PathVariable Long id) {
|
||||
MedicalRecord medicalRecord = medicalRecordService.getMedicalRecordDetails(id);
|
||||
return ResponseEntity.ok(medicalRecord);
|
||||
}*/
|
||||
|
||||
@PutMapping("/{id}")
|
||||
@Operation(summary = "อัปเดตบันทึกทางการแพทย์", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<MedicalRecord> updateMedicalRecord(@PathVariable Long id, @RequestBody MedicalRecordDTO medicalRecordDTO) {
|
||||
MedicalRecord updatedRecord = medicalRecordService.updateMedicalRecord(id, medicalRecordDTO);
|
||||
return ResponseEntity.ok(updatedRecord);
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
@Operation(summary = "ลบบันทึกทางการแพทย์", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<Void> deleteMedicalRecord(@PathVariable Long id) {
|
||||
medicalRecordService.deleteMedicalRecord(id);
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,66 @@
|
||||
package com.mirna.hospitalmanagementapi.application.controllers;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.NurseDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.Nurse;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.NurseService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1.0/nurses")
|
||||
@Tag(name = "nurse-controller")
|
||||
public class NurseController {
|
||||
|
||||
@Autowired
|
||||
private NurseService nurseService;
|
||||
|
||||
@PostMapping
|
||||
@Operation(summary = "เพิ่มข้อมูลพยาบาลใหม่เข้าสู่ระบบ", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<Nurse> addNurse(@RequestBody @Valid NurseDTO nurseDTO, UriComponentsBuilder uriBuilder) {
|
||||
Nurse newNurse = nurseService.addNurse(nurseDTO);
|
||||
URI uri = uriBuilder.path("/api/v1.0/nurses/{id}").buildAndExpand(newNurse.getId()).toUri();
|
||||
return ResponseEntity.created(uri).body(newNurse);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@Operation(summary = "ดึงรายการพยาบาลทั้งหมด", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<Page<Nurse>> getAllNurses(@PageableDefault(size = 10, page = 0, sort = {"name"}) Pageable pageable) {
|
||||
Page<Nurse> nurses = nurseService.getAllNurses(pageable);
|
||||
return ResponseEntity.ok(nurses);
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@Operation(summary = "ดึงข้อมูลพยาบาลตามรหัส (ID)", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<Nurse> getNurseById(@PathVariable Long id) throws EntityNotFoundException {
|
||||
Nurse nurse = nurseService.getNurseById(id);
|
||||
return ResponseEntity.ok(nurse);
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
@Operation(summary = "อัปเดตข้อมูลของพยาบาลที่มีอยู่", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<Nurse> updateNurse(@PathVariable Long id, @RequestBody @Valid NurseDTO nurseDTO) throws EntityNotFoundException {
|
||||
Nurse updatedNurse = nurseService.updateNurse(id, nurseDTO);
|
||||
return ResponseEntity.ok(updatedNurse);
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
@Operation(summary = "ลบพยาบาลออกจากระบบ", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<Void> deleteNurse(@PathVariable Long id) throws EntityNotFoundException {
|
||||
nurseService.deleteNurse(id);
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
package com.mirna.hospitalmanagementapi.application.controllers;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.NurseScheduleDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.NurseSchedule;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.NurseScheduleService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1.0/nurse-schedules")
|
||||
@Tag(name = "nurse-schedule-controller")
|
||||
public class NurseScheduleController {
|
||||
|
||||
@Autowired
|
||||
private NurseScheduleService nurseScheduleService;
|
||||
|
||||
@PostMapping
|
||||
@Operation(summary = "เพิ่มตารางเวรพยาบาลใหม่", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<Object> addNurseSchedule(@RequestBody @Valid NurseScheduleDTO nurseScheduleDTO, UriComponentsBuilder uriBuilder) {
|
||||
try {
|
||||
NurseSchedule newSchedule = nurseScheduleService.addNurseSchedule(nurseScheduleDTO);
|
||||
URI uri = uriBuilder.path("/api/v1.0/nurse-schedules/{id}").buildAndExpand(newSchedule.getId()).toUri();
|
||||
return ResponseEntity.created(uri).body(newSchedule);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// จับ Exception ที่มาจาก Service
|
||||
return ResponseEntity.badRequest().body(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@Operation(summary = "ดึงข้อมูลตารางเวรพยาบาลตามรหัส (ID)", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<NurseSchedule> getNurseScheduleById(@PathVariable Long id) throws EntityNotFoundException {
|
||||
NurseSchedule schedule = nurseScheduleService.getNurseScheduleById(id);
|
||||
return ResponseEntity.ok(schedule);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@Operation(summary = "ดึงข้อมูลตารางเวรพยาบาลทั้งหมดแบบมีการแบ่งหน้า (pagination)", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<Page<NurseSchedule>> getAllNurseSchedules(@PageableDefault(size = 10, page = 0, sort = {"startTime"}) Pageable pageable) {
|
||||
Page<NurseSchedule> schedules = nurseScheduleService.getAllNurseSchedules(pageable);
|
||||
return ResponseEntity.ok(schedules);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,66 @@
|
||||
package com.mirna.hospitalmanagementapi.application.controllers;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.OperatingRoomDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.OperatingRoom;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.OperatingRoomService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1.0/operating-rooms")
|
||||
@Tag(name = "operating-room-controller")
|
||||
public class OperatingRoomController {
|
||||
|
||||
@Autowired
|
||||
private OperatingRoomService operatingRoomService;
|
||||
|
||||
@PostMapping
|
||||
@Operation(summary = "เพิ่มห้องผ่าตัดใหม่เข้าสู่ระบบ", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<OperatingRoom> addOperatingRoom(@RequestBody @Valid OperatingRoomDTO operatingRoomDTO, UriComponentsBuilder uriBuilder) {
|
||||
OperatingRoom newRoom = operatingRoomService.addOperatingRoom(operatingRoomDTO);
|
||||
URI uri = uriBuilder.path("/api/v1.0/operating-rooms/{id}").buildAndExpand(newRoom.getId()).toUri();
|
||||
return ResponseEntity.created(uri).body(newRoom);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@Operation(summary = "ดึงรายการห้องผ่าตัดทั้งหมด", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<Page<OperatingRoom>> getAllOperatingRooms(@PageableDefault(size = 10, page = 0, sort = {"id"}) Pageable pageable) {
|
||||
Page<OperatingRoom> rooms = operatingRoomService.getAllOperatingRooms(pageable);
|
||||
return ResponseEntity.ok(rooms);
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@Operation(summary = "ดึงข้อมูลห้องผ่าตัดตามรหัส (ID)", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<OperatingRoom> getOperatingRoomById(@PathVariable Long id) throws EntityNotFoundException {
|
||||
OperatingRoom room = operatingRoomService.getOperatingRoomById(id);
|
||||
return ResponseEntity.ok(room);
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
@Operation(summary = "อัปเดตข้อมูลของห้องผ่าตัดที่มีอยู่", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<OperatingRoom> updateOperatingRoom(@PathVariable Long id, @RequestBody @Valid OperatingRoomDTO operatingRoomDTO) throws EntityNotFoundException {
|
||||
OperatingRoom updatedRoom = operatingRoomService.updateOperatingRoom(id, operatingRoomDTO);
|
||||
return ResponseEntity.ok(updatedRoom);
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
@Operation(summary = "ลบห้องผ่าตัดออกจากระบบ", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<Void> deleteOperatingRoom(@PathVariable Long id) throws EntityNotFoundException {
|
||||
operatingRoomService.deleteOperatingRoom(id);
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
package com.mirna.hospitalmanagementapi.application.controllers;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.OperatingRoomScheduleDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.OperatingRoomSchedule;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.OperatingRoomScheduleService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1.0/operating-room-schedules")
|
||||
@Tag(name = "operating-room-schedule-controller")
|
||||
public class OperatingRoomScheduleController {
|
||||
|
||||
@Autowired
|
||||
private OperatingRoomScheduleService operatingRoomScheduleService;
|
||||
|
||||
@PostMapping
|
||||
@Operation(summary = "เพิ่มตารางเวลาห้องผ่าตัดใหม่เข้าสู่ระบบ", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<OperatingRoomSchedule> addOperatingRoomSchedule(@RequestBody @Valid OperatingRoomScheduleDTO operatingRoomScheduleDTO, UriComponentsBuilder uriBuilder) {
|
||||
OperatingRoomSchedule newSchedule = operatingRoomScheduleService.addOperatingRoomSchedule(operatingRoomScheduleDTO);
|
||||
URI uri = uriBuilder.path("/api/v1.0/operating-room-schedules/{id}").buildAndExpand(newSchedule.getId()).toUri();
|
||||
return ResponseEntity.created(uri).body(newSchedule);
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@Operation(summary = "ดึงข้อมูลตารางเวลาห้องผ่าตัดตามรหัส (ID)", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<OperatingRoomSchedule> getOperatingRoomScheduleById(@PathVariable Long id) throws EntityNotFoundException {
|
||||
OperatingRoomSchedule schedule = operatingRoomScheduleService.getOperatingRoomScheduleById(id);
|
||||
return ResponseEntity.ok(schedule);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@Operation(summary = "ดึงข้อมูลตารางเวลาห้องผ่าตัดทั้งหมดแบบแบ่งหน้า (Pagination)", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<Page<OperatingRoomSchedule>> getAllOperatingRoomSchedules(@PageableDefault(size = 10, page = 0, sort = {"startTime"}) Pageable pageable) {
|
||||
Page<OperatingRoomSchedule> schedules = operatingRoomScheduleService.getAllOperatingRoomSchedules(pageable);
|
||||
return ResponseEntity.ok(schedules);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
package com.mirna.hospitalmanagementapi.infrastructure.controllers;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.PaymentDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.Payment;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.PaymentService;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1.0/payments")
|
||||
@SecurityRequirement(name = "bearer-key")
|
||||
public class PaymentController {
|
||||
|
||||
@Autowired
|
||||
private PaymentService paymentService;
|
||||
|
||||
@PostMapping
|
||||
public ResponseEntity<Payment> createPayment(@RequestBody @Valid PaymentDTO paymentDTO) {
|
||||
Payment newPayment = paymentService.createPayment(paymentDTO);
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(newPayment);
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public ResponseEntity<Payment> getPaymentById(@PathVariable Long id) {
|
||||
Payment payment = paymentService.getPaymentById(id);
|
||||
return ResponseEntity.ok(payment);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public ResponseEntity<Page<Payment>> getAllPayments(@PageableDefault(size = 10, sort = {"paymentDate"}) Pageable pageable) {
|
||||
Page<Payment> payments = paymentService.getAllPayments(pageable);
|
||||
return ResponseEntity.ok(payments);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
package com.mirna.hospitalmanagementapi.application.controllers;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.PrescriptionDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.PrescriptionResponseDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.Prescription;
|
||||
import com.mirna.hospitalmanagementapi.domain.exceptions.ConsultationValidationException;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.PrescriptionService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.UUID;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1.0/prescriptions")
|
||||
@Tag(name = "prescription-controller")
|
||||
public class PrescriptionController {
|
||||
|
||||
@Autowired
|
||||
private PrescriptionService prescriptionService;
|
||||
|
||||
@PostMapping
|
||||
@Operation(summary = "สร้างใบสั่งยาใหม่", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<PrescriptionResponseDTO> createPrescription(@RequestBody @Valid PrescriptionDTO dto)
|
||||
throws ConsultationValidationException, EntityNotFoundException {
|
||||
|
||||
Prescription savedPrescription = prescriptionService.createPrescription(dto);
|
||||
PrescriptionResponseDTO responseDTO = new PrescriptionResponseDTO(savedPrescription);
|
||||
return ResponseEntity.ok(responseDTO);
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@Operation(summary = "ดึงข้อมูลใบสั่งยาตาม ID", security = @SecurityRequirement(name = "bearer-key"))
|
||||
@PreAuthorize("hasAnyRole('ADMIN', 'DOCTOR') or (hasRole('PATIENT') and @prescriptionService.isOwner(#id, authentication.principal.id))")
|
||||
public ResponseEntity<PrescriptionResponseDTO> getPrescriptionById(@PathVariable UUID id)
|
||||
throws EntityNotFoundException {
|
||||
|
||||
Prescription prescription = prescriptionService.getPrescriptionById(id);
|
||||
PrescriptionResponseDTO responseDTO = new PrescriptionResponseDTO(prescription);
|
||||
return ResponseEntity.ok(responseDTO);
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
@Operation(summary = "แก้ไขข้อมูลใบสั่งยาตาม ID", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<PrescriptionResponseDTO> updatePrescription(@PathVariable UUID id, @RequestBody @Valid PrescriptionDTO dto)
|
||||
throws ConsultationValidationException, EntityNotFoundException {
|
||||
|
||||
Prescription updatedPrescription = prescriptionService.updatePrescription(id, dto);
|
||||
PrescriptionResponseDTO responseDTO = new PrescriptionResponseDTO(updatedPrescription);
|
||||
return ResponseEntity.ok(responseDTO);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
package com.mirna.hospitalmanagementapi.application.controllers;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.services.ReportService;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.FinancialReportDTO;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.AppointmentReportDTO;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.LowStockItemDTO;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1.0/reports")
|
||||
@SecurityRequirement(name = "bearer-key")
|
||||
public class ReportController {
|
||||
|
||||
@Autowired
|
||||
private ReportService reportService;
|
||||
|
||||
@GetMapping("/financial-overview")
|
||||
public ResponseEntity<List<FinancialReportDTO>> getFinancialOverview(
|
||||
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
|
||||
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) {
|
||||
|
||||
List<FinancialReportDTO> financialData = reportService.getFinancialReport(startDate, endDate);
|
||||
|
||||
if (financialData.isEmpty()) {
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
|
||||
return ResponseEntity.ok(financialData);
|
||||
}
|
||||
|
||||
@GetMapping("/inventory/low-stock")
|
||||
public ResponseEntity<Page<LowStockItemDTO>> getLowStockReport(@PageableDefault(size = 10, sort = "itemName") Pageable pageable) {
|
||||
Page<LowStockItemDTO> lowStockItems = reportService.getLowStockItems(pageable);
|
||||
|
||||
if (lowStockItems.isEmpty()) {
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
|
||||
return ResponseEntity.ok(lowStockItems);
|
||||
}
|
||||
|
||||
@GetMapping(value = "/appointments", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ResponseEntity<AppointmentReportDTO> getAppointmentReport(
|
||||
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
|
||||
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) {
|
||||
|
||||
AppointmentReportDTO report = reportService.getAppointmentReport(startDate, endDate);
|
||||
return ResponseEntity.ok(report);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package com.mirna.hospitalmanagementapi.application.controllers;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.Staff;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.StaffService;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* REST controller for managing staff.
|
||||
*
|
||||
* @author FlookSP
|
||||
* @version 1.0
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/v1.0/staff")
|
||||
@SecurityRequirement(name = "bearer-key")
|
||||
public class StaffController {
|
||||
|
||||
@Autowired
|
||||
private StaffService staffService;
|
||||
|
||||
@PostMapping
|
||||
@Transactional
|
||||
@Operation(
|
||||
summary = "เพิ่มเจ้าหน้าที่ใหม่",
|
||||
description = "ใช้สำหรับลงทะเบียนเจ้าหน้าที่ใหม่เข้าสู่ระบบ โดยจะสร้างบัญชีผู้ใช้ (User Account) ให้เจ้าหน้าที่พร้อมกัน",
|
||||
tags = {"Staff"}
|
||||
)
|
||||
public ResponseEntity<Staff> addStaff(@RequestBody @Valid Staff staff, UriComponentsBuilder uriBuilder) {
|
||||
Staff createdStaff = staffService.addStaff(staff);
|
||||
URI uri = uriBuilder.path("/api/v1.0/staff/{id}").buildAndExpand(createdStaff.getId()).toUri();
|
||||
return ResponseEntity.created(uri).body(createdStaff);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,130 @@
|
||||
package com.mirna.hospitalmanagementapi.application.controllers;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.auth.UserUpdatePasswordDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.auth.UserUpdateRoleDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.auth.UserUpdateUsernameDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.auth.User;
|
||||
import com.mirna.hospitalmanagementapi.domain.enums.Role;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.UserService;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
|
||||
/**
|
||||
* REST controller for managing users.
|
||||
*
|
||||
* @author FlookSP
|
||||
* @version 1.2
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/v1.0/users")
|
||||
public class UserController {
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
// Helper method เพื่อตรวจสอบสิทธิ์การเข้าถึง
|
||||
private void checkUserAccess(Long targetUserId) {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
User currentUser = (User) authentication.getPrincipal();
|
||||
|
||||
// อนุญาตถ้าผู้ใช้ปัจจุบันเป็น ADMIN หรือเป็นเจ้าของข้อมูล
|
||||
boolean isAdmin = currentUser.getRole().equals(Role.ROLE_ADMIN);
|
||||
boolean isOwner = currentUser.getId().equals(targetUserId);
|
||||
|
||||
if (!isAdmin && !isOwner) {
|
||||
throw new AccessDeniedException("You do not have permission to access this resource.");
|
||||
}
|
||||
}
|
||||
|
||||
// Endpoint สำหรับอัปเดตชื่อผู้ใช้งาน (login)
|
||||
@PutMapping("/{id}/username")
|
||||
@Transactional
|
||||
@Operation(summary = "อัปเดตชื่อผู้ใช้งาน", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<User> updateUsername(@PathVariable Long id, @RequestBody @Valid UserUpdateUsernameDTO userUpdateUsernameDTO) {
|
||||
checkUserAccess(id);
|
||||
User updatedUser = userService.updateUsername(id, userUpdateUsernameDTO);
|
||||
return ResponseEntity.ok(updatedUser);
|
||||
}
|
||||
|
||||
// Endpoint สำหรับอัปเดตรหัสผ่าน
|
||||
@PutMapping("/{id}/password")
|
||||
@Transactional
|
||||
@Operation(summary = "อัปเดตรหัสผ่าน", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<User> updatePassword(@PathVariable Long id, @RequestBody @Valid UserUpdatePasswordDTO userUpdatePasswordDTO) {
|
||||
checkUserAccess(id);
|
||||
User updatedUser = userService.updatePassword(id, userUpdatePasswordDTO);
|
||||
return ResponseEntity.ok(updatedUser);
|
||||
}
|
||||
|
||||
// Endpoint สำหรับอัปเดต Role (สำหรับ Admin เท่านั้น)
|
||||
@PutMapping("/{id}/role")
|
||||
@Transactional
|
||||
@Operation(summary = "อัปเดตบทบาท (Role) ของผู้ใช้งาน", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<User> updateRole(@PathVariable Long id, @RequestBody @Valid UserUpdateRoleDTO userUpdateRoleDTO) {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
User currentUser = (User) authentication.getPrincipal();
|
||||
|
||||
if (!currentUser.getRole().equals(Role.ROLE_ADMIN)) {
|
||||
throw new AccessDeniedException("You do not have permission to update user roles.");
|
||||
}
|
||||
User updatedUser = userService.updateRole(id, userUpdateRoleDTO);
|
||||
return ResponseEntity.ok(updatedUser);
|
||||
}
|
||||
|
||||
// Endpoint ใหม่สำหรับปิดใช้งานบัญชีผู้ใช้งาน
|
||||
@PatchMapping("/{id}/deactivate")
|
||||
@Transactional
|
||||
@Operation(summary = "ปิดใช้งานบัญชีผู้ใช้งาน", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<Void> deactivateUser(@PathVariable Long id) {
|
||||
// เฉพาะ ADMIN เท่านั้นที่สามารถปิดใช้งานบัญชีได้
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
User currentUser = (User) authentication.getPrincipal();
|
||||
|
||||
if (!currentUser.getRole().equals(Role.ROLE_ADMIN)) {
|
||||
throw new AccessDeniedException("You do not have permission to deactivate user accounts.");
|
||||
}
|
||||
// ตรวจสอบว่า ADMIN จะไม่สามารถปิดใช้งานบัญชีของตัวเองได้
|
||||
if (currentUser.getId().equals(id)) {
|
||||
throw new IllegalArgumentException("You cannot deactivate your own account.");
|
||||
}
|
||||
userService.deactivateUser(id);
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
|
||||
// Endpoint ใหม่สำหรับเปิดใช้งานบัญชีผู้ใช้งาน
|
||||
@PatchMapping("/{id}/activate")
|
||||
@Transactional
|
||||
@Operation(summary = "เปิดใช้งานบัญชีผู้ใช้งาน", security = @SecurityRequirement(name = "bearer-key"))
|
||||
public ResponseEntity<Void> activateUser(@PathVariable Long id) {
|
||||
// เฉพาะ ADMIN เท่านั้นที่สามารถเปิดใช้งานบัญชีได้
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
User currentUser = (User) authentication.getPrincipal();
|
||||
|
||||
if (!currentUser.getRole().equals(Role.ROLE_ADMIN)) {
|
||||
throw new AccessDeniedException("You do not have permission to activate user accounts.");
|
||||
}
|
||||
|
||||
userService.activateUser(id);
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
|
||||
@ExceptionHandler(AccessDeniedException.class)
|
||||
public ResponseEntity<String> handleAccessDeniedException(AccessDeniedException ex) {
|
||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(ex.getMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler(IllegalArgumentException.class)
|
||||
public ResponseEntity<String> handleIllegalArgumentException(IllegalArgumentException ex) {
|
||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(ex.getMessage());
|
||||
}
|
||||
}
|
||||
@ -1,10 +1,8 @@
|
||||
package com.mirna.hospitalmanagementapi.application.controllers.auth;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
@ -14,8 +12,28 @@ import com.mirna.hospitalmanagementapi.domain.dtos.auth.UserDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.auth.User;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.auth.AuthService;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.auth.jwt.TokenService;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.PatientService;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.auth.PatientRegistrationDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.auth.DoctorRegistrationDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.auth.LinkPatientToUserDTO;
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import jakarta.persistence.PersistenceException;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.auth.StaffRegistrationDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.Staff;
|
||||
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import com.mirna.hospitalmanagementapi.domain.enums.Role;
|
||||
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.auth.NurseRegistrationDTO;
|
||||
|
||||
/**
|
||||
* A Spring REST controller for managing authentication and user information.
|
||||
@ -27,45 +45,126 @@ import jakarta.validation.Valid;
|
||||
@RequestMapping("/api/auth")
|
||||
public class AuthenticationController {
|
||||
|
||||
@Autowired
|
||||
private AuthService authService;
|
||||
@Autowired
|
||||
private AuthService authService;
|
||||
|
||||
@Autowired
|
||||
private TokenService tokenService;
|
||||
@Autowired
|
||||
private TokenService tokenService;
|
||||
|
||||
/**
|
||||
* Performs the user login
|
||||
*
|
||||
* @param userDTO A data transfer object containing the user data to perform the login
|
||||
*
|
||||
* @return The authorization token if successful, or an unauthorized status if there is an error.
|
||||
*/
|
||||
@PostMapping(value = "/login")
|
||||
public ResponseEntity<Object> login(@RequestBody @Valid UserDTO userDTO) {
|
||||
@Autowired
|
||||
private PatientService patientService;
|
||||
|
||||
Authentication auth = authService.login(userDTO);
|
||||
/**
|
||||
* Performs the user login
|
||||
*
|
||||
* @param userDTO A data transfer object containing the user data to perform the login
|
||||
* * @return The authorization token if successful, or an unauthorized status if there is an error.
|
||||
*/
|
||||
@PostMapping(value = "/login")
|
||||
public ResponseEntity<Object> login(@RequestBody @Valid UserDTO userDTO) {
|
||||
|
||||
User authenticatedUser = (User) auth.getPrincipal();
|
||||
var auth = authService.login(userDTO);
|
||||
|
||||
String token = tokenService.generateToken(authenticatedUser);
|
||||
var authenticatedUser = (User) auth.getPrincipal();
|
||||
|
||||
return ResponseEntity.ok(token);
|
||||
}
|
||||
String token = tokenService.generateToken(authenticatedUser);
|
||||
|
||||
/**
|
||||
* Performs the user registration
|
||||
*
|
||||
* @param userDTO A data transfer object containing the user data to perform the registration
|
||||
*
|
||||
* @return The registered user if successful, or null if there is an error.
|
||||
*/
|
||||
return ResponseEntity.ok(token);
|
||||
}
|
||||
|
||||
@PostMapping(value = "/register")
|
||||
public ResponseEntity<Object> register(@RequestBody @Valid UserDTO userDTO) {
|
||||
/**
|
||||
* Performs the user registration
|
||||
*
|
||||
* @param userDTO A data transfer object containing the user data to perform the registration
|
||||
* * @return The registered user if successful, or null if there is an error.
|
||||
*/
|
||||
/*@PostMapping(value = "/register")
|
||||
public ResponseEntity<Object> register(@RequestBody @Valid UserDTO userDTO) {
|
||||
User user = authService.register(userDTO);
|
||||
return ResponseEntity.ok(user);
|
||||
}*/
|
||||
|
||||
User user = authService.register(userDTO);
|
||||
/**
|
||||
* Performs the user registration (patients)
|
||||
*
|
||||
* @param registrationDTO Data transfer object containing user and patient creation
|
||||
* @return A user object including the credentials
|
||||
*/
|
||||
@PostMapping(value = "/register-patient")
|
||||
public ResponseEntity<Object> registerPatient(@RequestBody @Valid PatientRegistrationDTO registrationDTO) {
|
||||
User user = authService.registerPatient(registrationDTO);
|
||||
return ResponseEntity.ok(user);
|
||||
}
|
||||
|
||||
return ResponseEntity.ok(user);
|
||||
}
|
||||
/**
|
||||
* Registers a new user account for a doctor and links it to an existing doctor record.
|
||||
*
|
||||
* @param registrationDTO Data transfer object containing user credentials and CRM for linking
|
||||
* @return A new user object if registration and linking are successful.
|
||||
*/
|
||||
@PostMapping(value = "/register-doctor-and-link")
|
||||
public ResponseEntity<Object> registerDoctor(@RequestBody @Valid DoctorRegistrationDTO registrationDTO) {
|
||||
try {
|
||||
User newUser = authService.registerDoctor(registrationDTO);
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(newUser);
|
||||
} catch (PersistenceException e) {
|
||||
return ResponseEntity.badRequest().body(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Links an existing patient record to a new user account
|
||||
*
|
||||
* @param linkPatientToUserDTO A data transfer object containing the patient ID and new user data
|
||||
*
|
||||
* @return A success message if the linking is successful, or an error message otherwise
|
||||
*/
|
||||
@PostMapping(value = "/link-patient-to-user")
|
||||
public ResponseEntity<String> linkPatientToUser(@RequestBody @Valid LinkPatientToUserDTO linkPatientToUserDTO) {
|
||||
try {
|
||||
patientService.linkPatientToUser(linkPatientToUserDTO);
|
||||
return ResponseEntity.ok("Patient successfully linked to a new user account.");
|
||||
} catch (IllegalArgumentException e) {
|
||||
return ResponseEntity.badRequest().body(e.getMessage());
|
||||
} catch (EntityNotFoundException e) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new user account for a nurse and links it to an existing nurse record.
|
||||
*
|
||||
* @param registrationDTO Data transfer object containing user credentials and license number for linking
|
||||
* @return A new user object if registration and linking are successful.
|
||||
*/
|
||||
@PostMapping(value = "/register-nurse-and-link")
|
||||
public ResponseEntity<Object> registerNurse(@RequestBody @Valid NurseRegistrationDTO registrationDTO) {
|
||||
try {
|
||||
User newUser = authService.registerNurseAndLink(registrationDTO);
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(newUser);
|
||||
} catch (PersistenceException e) {
|
||||
return ResponseEntity.badRequest().body(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/*@PostMapping("/register-staff")
|
||||
@Transactional
|
||||
@Operation(
|
||||
summary = "ลงทะเบียนเจ้าหน้าที่ใหม่",
|
||||
security = @SecurityRequirement(name = "bearer-key") // เพิ่มบรรทัดนี้
|
||||
)
|
||||
public ResponseEntity<Staff> registerStaff(@RequestBody @Valid StaffRegistrationDTO dto) {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
if (!authentication.getAuthorities().stream().anyMatch(a -> a.getAuthority().equals(Role.ROLE_ADMIN.name()))) {
|
||||
throw new AccessDeniedException("Only ADMIN can register a new staff member.");
|
||||
}
|
||||
|
||||
// ตรวจสอบว่า role ที่ต้องการลงทะเบียนเป็น Staff roles
|
||||
if (dto.role() != Role.ROLE_NURSE && dto.role() != Role.ROLE_RECEPTIONIST && dto.role() != Role.ROLE_PHARMACIST) {
|
||||
throw new IllegalArgumentException("Invalid role for staff registration. Allowed roles are: NURSE, RECEPTIONIST, PHARMACIST");
|
||||
}
|
||||
|
||||
Staff createdStaff = authService.registerStaff(dto);
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(createdStaff);
|
||||
}*/
|
||||
}
|
||||
@ -0,0 +1,89 @@
|
||||
package com.mirna.hospitalmanagementapi.application.services;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.Billing;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.BillableItem;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.MedicalRecord;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.BillingDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.BillableItemDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.enums.PaymentStatus;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.BillingRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.MedicalRecordRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.BillingService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class BillingServiceImpl implements BillingService {
|
||||
|
||||
@Autowired
|
||||
private BillingRepository billingRepository;
|
||||
|
||||
@Autowired
|
||||
private MedicalRecordRepository medicalRecordRepository;
|
||||
|
||||
@Override
|
||||
public Billing createBilling(BillingDTO billingDTO) {
|
||||
MedicalRecord medicalRecord = medicalRecordRepository.findById(billingDTO.getMedicalRecordId())
|
||||
.orElseThrow(() -> new EntityNotFoundException("Medical record not found with ID: " + billingDTO.getMedicalRecordId()));
|
||||
|
||||
Billing billing = new Billing();
|
||||
billing.setMedicalRecord(medicalRecord);
|
||||
billing.setIssueDate(LocalDateTime.now());
|
||||
billing.setPaymentStatus(PaymentStatus.PENDING);
|
||||
|
||||
// Map DTOs to entities and calculate total amount
|
||||
List<BillableItem> billableItems = billingDTO.getBillableItems().stream()
|
||||
.map(itemDTO -> {
|
||||
BillableItem item = new BillableItem();
|
||||
item.setItemDescription(itemDTO.getItemDescription());
|
||||
item.setQuantity(itemDTO.getQuantity());
|
||||
item.setUnitPrice(itemDTO.getUnitPrice());
|
||||
item.setItemAmount(itemDTO.getUnitPrice().multiply(BigDecimal.valueOf(itemDTO.getQuantity())));
|
||||
item.setBilling(billing);
|
||||
return item;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
BigDecimal totalAmount = billableItems.stream()
|
||||
.map(BillableItem::getItemAmount)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
|
||||
billing.setBillableItems(billableItems);
|
||||
billing.setTotalAmount(totalAmount);
|
||||
|
||||
return billingRepository.save(billing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Billing getBillingById(Long id) {
|
||||
return billingRepository.findById(id)
|
||||
.orElseThrow(() -> new EntityNotFoundException("Billing not found with ID: " + id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Billing updateBilling(Long id, BillingDTO billingDTO) {
|
||||
Billing existingBilling = getBillingById(id);
|
||||
// You can add logic here to update existing billing data
|
||||
// For simplicity, we'll just demonstrate fetching the entity
|
||||
return billingRepository.save(existingBilling);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteBilling(Long id) {
|
||||
billingRepository.deleteById(id);
|
||||
}
|
||||
|
||||
// Assuming Billing entity has a getMedicalRecord() method
|
||||
// and MedicalRecord entity has a getPatient() method
|
||||
@Override
|
||||
public boolean isOwner(Long billingId, Long patientId) {
|
||||
return billingRepository.findById(billingId)
|
||||
.map(billing -> billing.getMedicalRecord().getPatient().getId().equals(patientId))
|
||||
.orElse(false);
|
||||
}
|
||||
}
|
||||
@ -1,12 +1,8 @@
|
||||
package com.mirna.hospitalmanagementapi.application.services;
|
||||
|
||||
import org.apache.coyote.BadRequestException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.application.usecase.consultation.FindConsultationByDoctorAndDateUseCase;
|
||||
import com.mirna.hospitalmanagementapi.application.usecase.consultation.FindConsultationByIdUseCase;
|
||||
import com.mirna.hospitalmanagementapi.application.usecase.consultation.FindConsultationByPatientAndDateUseCase;
|
||||
import com.mirna.hospitalmanagementapi.application.usecase.consultation.SaveConsultationUseCase;
|
||||
import com.mirna.hospitalmanagementapi.application.usecase.doctor.FindDoctorByIdUseCase;
|
||||
import com.mirna.hospitalmanagementapi.application.usecase.doctor.FindOneFreeDoctorBySpecialtyUseCase;
|
||||
@ -18,116 +14,134 @@ import com.mirna.hospitalmanagementapi.domain.entities.Doctor;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.Patient;
|
||||
import com.mirna.hospitalmanagementapi.domain.exceptions.ConsultationValidationException;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.ConsultationService;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.DoctorScheduleService;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.ConsultationRepository;
|
||||
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import java.time.LocalTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* This class is an implementation of the ConsultationService interface.
|
||||
*
|
||||
* This class provides methods to perform operations on consultations
|
||||
*
|
||||
* @author Mirna Gama
|
||||
* @version 1.0
|
||||
*/
|
||||
@Service
|
||||
public class ConsultationServiceImpl implements ConsultationService {
|
||||
|
||||
@Autowired
|
||||
private SaveConsultationUseCase saveConsultation;
|
||||
@Autowired
|
||||
private SaveConsultationUseCase saveConsultation;
|
||||
|
||||
@Autowired
|
||||
private FindConsultationByIdUseCase findConsultationById;
|
||||
@Autowired
|
||||
private FindConsultationByIdUseCase findConsultationById;
|
||||
|
||||
@Autowired
|
||||
private FindConsultationByDoctorAndDateUseCase findConsultationByDoctorAndDate;
|
||||
@Autowired
|
||||
private ConsultationRepository consultationRepository;
|
||||
|
||||
@Autowired
|
||||
private FindConsultationByPatientAndDateUseCase findConsultationByPatientAndDate;
|
||||
@Autowired
|
||||
private FindPatientByIdUseCase findPatientById;
|
||||
|
||||
@Autowired
|
||||
private FindPatientByIdUseCase findPatientById;
|
||||
@Autowired
|
||||
private FindDoctorByIdUseCase findDoctorById;
|
||||
|
||||
@Autowired
|
||||
private FindDoctorByIdUseCase findDoctorById;
|
||||
@Autowired
|
||||
private FindOneFreeDoctorBySpecialtyUseCase findOneFreeDoctorBySpecialty;
|
||||
|
||||
@Autowired
|
||||
private FindOneFreeDoctorBySpecialtyUseCase findOneFreeDoctorBySpecialty;
|
||||
@Autowired
|
||||
private DoctorScheduleService doctorScheduleService;
|
||||
|
||||
/**
|
||||
* Adds a new consultation to the repository.
|
||||
*
|
||||
* @param consultationDTO A data transfer object representing a consultation to add.
|
||||
* @return The saved consultation if successful, or throws an exception if there is an error.
|
||||
* @throws ConsultationValidationException if there is a validation error
|
||||
*/
|
||||
@Override
|
||||
public Consultation addConsultation(ConsultationDTO consultationDTO) throws ConsultationValidationException {
|
||||
private static final ZoneOffset BANGKOK_ZONE_OFFSET = ZoneOffset.ofHours(7);
|
||||
|
||||
Patient patient = findPatientById.execute(consultationDTO.patientId());
|
||||
@Override
|
||||
@Transactional
|
||||
public Consultation addConsultation(ConsultationDTO consultationDTO) throws ConsultationValidationException {
|
||||
Patient patient = validatePatient(consultationDTO.patientId(), consultationDTO.consultationDate());
|
||||
Doctor doctor = validateAndFindDoctor(consultationDTO);
|
||||
validatePatientAndDoctorAvailability(patient, doctor, consultationDTO.consultationDate());
|
||||
|
||||
if (!patient.getActive())
|
||||
throw new ConsultationValidationException("This patient is not active");
|
||||
Consultation consultation = new Consultation(patient, doctor, consultationDTO.consultationDate());
|
||||
|
||||
if (findConsultationByPatientAndDate.execute(patient.getId(), consultationDTO.consultationDate()) != null)
|
||||
throw new ConsultationValidationException("This patient is not free on this date");
|
||||
return saveConsultation.execute(consultation);
|
||||
}
|
||||
|
||||
Doctor doctor = null;
|
||||
private Patient validatePatient(Long patientId, OffsetDateTime consultationDate) throws ConsultationValidationException {
|
||||
if (patientId == null) {
|
||||
throw new ConsultationValidationException("Patient ID cannot be null");
|
||||
}
|
||||
|
||||
if (consultationDTO.doctorId() != null) {
|
||||
Patient patient = findPatientById.execute(patientId);
|
||||
|
||||
doctor = findDoctorById.execute(consultationDTO.doctorId());
|
||||
if (patient == null) {
|
||||
throw new ConsultationValidationException("This patient is not found");
|
||||
}
|
||||
if (!patient.getActive()) {
|
||||
throw new ConsultationValidationException("This patient is not active");
|
||||
}
|
||||
|
||||
if (!doctor.getActive())
|
||||
throw new ConsultationValidationException("This doctor is not active");
|
||||
OffsetDateTime consultationDateInBkkZone = consultationDate.withOffsetSameInstant(BANGKOK_ZONE_OFFSET);
|
||||
OffsetDateTime startOfDay = consultationDateInBkkZone.with(LocalTime.MIN);
|
||||
OffsetDateTime endOfDay = consultationDateInBkkZone.with(LocalTime.MAX);
|
||||
|
||||
if (findConsultationByDoctorAndDate.execute(doctor.getId(), consultationDTO.consultationDate()) != null)
|
||||
throw new ConsultationValidationException("This doctor is not free on this date");
|
||||
// แก้ไขบรรทัดนี้: ส่งพารามิเตอร์ที่ถูกต้องไปยัง Repository
|
||||
if (consultationRepository.findConsultationByPatientAndDate(patient.getId(), startOfDay, endOfDay) != null) {
|
||||
throw new ConsultationValidationException("This patient is not free on this date");
|
||||
}
|
||||
return patient;
|
||||
}
|
||||
|
||||
} else if (consultationDTO.specialty() != null) {
|
||||
private Doctor validateAndFindDoctor(ConsultationDTO consultationDTO) throws ConsultationValidationException {
|
||||
Doctor doctor = null;
|
||||
OffsetDateTime consultationDateInBkkZone = consultationDTO.consultationDate().withOffsetSameInstant(BANGKOK_ZONE_OFFSET);
|
||||
|
||||
doctor = findOneFreeDoctorBySpecialty.execute(consultationDTO.specialty(),
|
||||
consultationDTO.consultationDate());
|
||||
if (consultationDTO.doctorId() != null) {
|
||||
doctor = findDoctorById.execute(consultationDTO.doctorId());
|
||||
} else if (consultationDTO.specialty() != null) {
|
||||
doctor = findOneFreeDoctorBySpecialty.execute(consultationDTO.specialty(), consultationDateInBkkZone);
|
||||
} else {
|
||||
throw new ConsultationValidationException("At least the specialty or doctor ID must be filled in");
|
||||
}
|
||||
|
||||
if (doctor == null) throw new ConsultationValidationException("There is no free doctor for this date with this specialty");
|
||||
if (doctor == null) {
|
||||
throw new ConsultationValidationException("No doctors found at the requested time or specialty.");
|
||||
}
|
||||
return doctor;
|
||||
}
|
||||
|
||||
} else {
|
||||
throw new ConsultationValidationException("At least the specialty or doctor ID must be filled in");
|
||||
}
|
||||
private void validatePatientAndDoctorAvailability(Patient patient, Doctor doctor, OffsetDateTime consultationDate) throws ConsultationValidationException {
|
||||
OffsetDateTime consultationDateInBkkZone = consultationDate.withOffsetSameInstant(BANGKOK_ZONE_OFFSET);
|
||||
|
||||
Consultation consultation = new Consultation(patient, doctor, consultationDTO.consultationDate());
|
||||
OffsetDateTime startOfDay = consultationDateInBkkZone.with(LocalTime.MIN);
|
||||
OffsetDateTime endOfDay = consultationDateInBkkZone.with(LocalTime.MAX);
|
||||
|
||||
return saveConsultation.execute(consultation);
|
||||
}
|
||||
// แก้ไขบรรทัดนี้: ส่งพารามิเตอร์ที่ถูกต้องไปยัง Repository
|
||||
if (consultationRepository.findConsultationByDoctorAndDate(doctor.getId(), startOfDay, endOfDay) != null) {
|
||||
throw new ConsultationValidationException("This doctor is not free on this date");
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a stored consultation by id.
|
||||
*
|
||||
* @param id A long representing the consultation's unique identifier
|
||||
* @return The corresponding consultation if successful, or throws an exception if it is non-existent.
|
||||
*/
|
||||
@Override
|
||||
public Consultation findConsultationById(Long id) {
|
||||
Consultation consultation = findConsultationById.execute(id);
|
||||
boolean isDoctorAvailable = doctorScheduleService.isDoctorAvailable(
|
||||
doctor.getId(),
|
||||
consultationDateInBkkZone.getDayOfWeek(),
|
||||
consultationDateInBkkZone.toLocalTime()
|
||||
);
|
||||
|
||||
if (consultation == null)
|
||||
throw new EntityNotFoundException("No existing consultation with this id");
|
||||
if (!isDoctorAvailable) {
|
||||
throw new ConsultationValidationException("The selected doctor is not on duty at the requested time.");
|
||||
}
|
||||
}
|
||||
|
||||
return consultation;
|
||||
}
|
||||
@Override
|
||||
public Consultation findConsultationById(Long id) {
|
||||
Consultation consultation = findConsultationById.execute(id);
|
||||
|
||||
/**
|
||||
* Cancels and updates an existing query in the repository
|
||||
* @param consultationCanceledDTO A data transfer object representing the consultation that will be canceled.
|
||||
* @return The canceled consultation if successful, or throws an exception if there is an error.
|
||||
*/
|
||||
@Override
|
||||
public Consultation cancelConsultation(ConsultationCanceledDTO consultationCanceledDTO) {
|
||||
Consultation consultation = this.findConsultationById(consultationCanceledDTO.consultationId());
|
||||
if (consultation == null)
|
||||
throw new EntityNotFoundException("No existing consultation with this id");
|
||||
|
||||
consultation.setCanceled(true);
|
||||
consultation.setReasonCancellation(consultationCanceledDTO.reasonCancellation());
|
||||
|
||||
return saveConsultation.execute(consultation);
|
||||
}
|
||||
return consultation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Consultation cancelConsultation(ConsultationCanceledDTO consultationCanceledDTO) {
|
||||
Consultation consultation = this.findConsultationById(consultationCanceledDTO.consultationId());
|
||||
consultation.setCanceled(true);
|
||||
consultation.setReasonCancellation(consultationCanceledDTO.reasonCancellation());
|
||||
return saveConsultation.execute(consultation);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package com.mirna.hospitalmanagementapi.application.services;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.DoctorSchedule;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.DoctorScheduleRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.DoctorScheduleService;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.LocalTime;
|
||||
|
||||
@Service
|
||||
public class DoctorScheduleServiceImpl implements DoctorScheduleService {
|
||||
|
||||
@Autowired
|
||||
private DoctorScheduleRepository doctorScheduleRepository;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public DoctorSchedule saveDoctorSchedule(DoctorSchedule doctorSchedule) {
|
||||
return doctorScheduleRepository.save(doctorSchedule);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDoctorAvailable(Long doctorId, DayOfWeek day, LocalTime time) {
|
||||
// Step 1: Find the doctor's schedule for that day.
|
||||
DoctorSchedule doctorSchedule = doctorScheduleRepository.findByDoctorIdAndDayOfWeek(doctorId, day);
|
||||
|
||||
// Step 2: If no schedule is found, return false immediately.
|
||||
if (doctorSchedule == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LocalTime businessHourStart = doctorSchedule.getStartTime();
|
||||
LocalTime businessHourEnd = doctorSchedule.getEndTime();
|
||||
|
||||
// Step 3: Check if the consultation time is within the working hours.
|
||||
// We use isAfter() with a check for equality to include the start time.
|
||||
// We use isBefore() to exclude the end time, as is standard practice for time slots.
|
||||
return (time.equals(businessHourStart) || time.isAfter(businessHourStart)) && time.isBefore(businessHourEnd);
|
||||
}
|
||||
}
|
||||
@ -100,13 +100,13 @@ public class DoctorServiceImpl implements DoctorService {
|
||||
throw new EntityNotFoundException("No existing doctor with this id");
|
||||
}
|
||||
|
||||
if (doctorUpdatedDataDTO.name() != null) {
|
||||
doctor.setName(doctorUpdatedDataDTO.name());
|
||||
}
|
||||
if (doctorUpdatedDataDTO.name() != null) {
|
||||
doctor.setName(doctorUpdatedDataDTO.name());
|
||||
}
|
||||
|
||||
if (doctorUpdatedDataDTO.telephone() != null) {
|
||||
doctor.setName(doctorUpdatedDataDTO.telephone());
|
||||
}
|
||||
if (doctorUpdatedDataDTO.telephone() != null) {
|
||||
doctor.setTelephone(doctorUpdatedDataDTO.telephone());
|
||||
}
|
||||
|
||||
if (doctorUpdatedDataDTO.address() != null) {
|
||||
|
||||
|
||||
@ -0,0 +1,94 @@
|
||||
package com.mirna.hospitalmanagementapi.application.services;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.Billing;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.InsuranceClaim;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.InsuranceProvider;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.InsuranceClaimDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.enums.ClaimStatus; // <-- นำเข้า Enum
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.BillingRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.InsuranceClaimRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.InsuranceProviderRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.InsuranceClaimService;
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class InsuranceClaimServiceImpl implements InsuranceClaimService {
|
||||
|
||||
@Autowired
|
||||
private InsuranceClaimRepository insuranceClaimRepository;
|
||||
|
||||
@Autowired
|
||||
private BillingRepository billingRepository;
|
||||
|
||||
@Autowired
|
||||
private InsuranceProviderRepository insuranceProviderRepository;
|
||||
|
||||
@Override
|
||||
public InsuranceClaim createInsuranceClaim(InsuranceClaimDTO insuranceClaimDTO) {
|
||||
Billing billing = billingRepository.findById(insuranceClaimDTO.getBillingId())
|
||||
.orElseThrow(() -> new EntityNotFoundException("Billing not found with ID: " + insuranceClaimDTO.getBillingId()));
|
||||
|
||||
InsuranceProvider insuranceProvider = insuranceProviderRepository.findById(insuranceClaimDTO.getInsuranceProviderId())
|
||||
.orElseThrow(() -> new EntityNotFoundException("Insurance Provider not found with ID: " + insuranceClaimDTO.getInsuranceProviderId()));
|
||||
|
||||
InsuranceClaim claim = new InsuranceClaim();
|
||||
claim.setBilling(billing);
|
||||
claim.setInsuranceProvider(insuranceProvider);
|
||||
claim.setClaimNumber(insuranceClaimDTO.getClaimNumber());
|
||||
claim.setSubmissionDate(insuranceClaimDTO.getSubmissionDate());
|
||||
claim.setApprovedAmount(insuranceClaimDTO.getApprovedAmount());
|
||||
|
||||
// แปลง String เป็น Enum
|
||||
if (insuranceClaimDTO.getClaimStatus() != null) {
|
||||
claim.setClaimStatus(ClaimStatus.valueOf(insuranceClaimDTO.getClaimStatus().toUpperCase()));
|
||||
}
|
||||
|
||||
return insuranceClaimRepository.save(claim);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InsuranceClaim getInsuranceClaimById(Long id) {
|
||||
return insuranceClaimRepository.findById(id)
|
||||
.orElseThrow(() -> new EntityNotFoundException("Insurance Claim not found with ID: " + id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<InsuranceClaim> getAllInsuranceClaims(Pageable pageable) {
|
||||
return insuranceClaimRepository.findAll(pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InsuranceClaim updateInsuranceClaim(Long id, InsuranceClaimDTO insuranceClaimDTO) {
|
||||
InsuranceClaim existingClaim = getInsuranceClaimById(id);
|
||||
|
||||
Billing billing = billingRepository.findById(insuranceClaimDTO.getBillingId())
|
||||
.orElseThrow(() -> new EntityNotFoundException("Billing not found with ID: " + insuranceClaimDTO.getBillingId()));
|
||||
|
||||
InsuranceProvider insuranceProvider = insuranceProviderRepository.findById(insuranceClaimDTO.getInsuranceProviderId())
|
||||
.orElseThrow(() -> new EntityNotFoundException("Insurance Provider not found with ID: " + insuranceClaimDTO.getInsuranceProviderId()));
|
||||
|
||||
existingClaim.setBilling(billing);
|
||||
existingClaim.setInsuranceProvider(insuranceProvider);
|
||||
existingClaim.setClaimNumber(insuranceClaimDTO.getClaimNumber());
|
||||
existingClaim.setSubmissionDate(insuranceClaimDTO.getSubmissionDate());
|
||||
existingClaim.setApprovedAmount(insuranceClaimDTO.getApprovedAmount());
|
||||
|
||||
// แปลง String เป็น Enum
|
||||
if (insuranceClaimDTO.getClaimStatus() != null) {
|
||||
existingClaim.setClaimStatus(ClaimStatus.valueOf(insuranceClaimDTO.getClaimStatus().toUpperCase()));
|
||||
}
|
||||
|
||||
return insuranceClaimRepository.save(existingClaim);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteInsuranceClaim(Long id) {
|
||||
insuranceClaimRepository.deleteById(id);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,81 @@
|
||||
package com.mirna.hospitalmanagementapi.application.services;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.InsuranceProviderDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.InsuranceProvider;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.InsuranceProviderRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.InsuranceProviderService;
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class InsuranceProviderServiceImpl implements InsuranceProviderService {
|
||||
|
||||
@Autowired
|
||||
private InsuranceProviderRepository insuranceProviderRepository;
|
||||
|
||||
/**
|
||||
* Adds a new insurance provider to the database.
|
||||
*/
|
||||
@Override
|
||||
public InsuranceProvider addInsuranceProvider(InsuranceProviderDTO insuranceProviderDTO) {
|
||||
InsuranceProvider provider = new InsuranceProvider();
|
||||
provider.setProviderName(insuranceProviderDTO.providerName());
|
||||
provider.setContactPerson(insuranceProviderDTO.contactPerson());
|
||||
provider.setContactEmail(insuranceProviderDTO.contactEmail());
|
||||
provider.setPhoneNumber(insuranceProviderDTO.phoneNumber());
|
||||
return insuranceProviderRepository.save(provider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all insurance providers from the database.
|
||||
*/
|
||||
@Override
|
||||
public List<InsuranceProvider> getAllInsuranceProviders() {
|
||||
return insuranceProviderRepository.findAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds an insurance provider by its ID.
|
||||
*/
|
||||
@Override
|
||||
public InsuranceProvider getInsuranceProviderById(Long id) throws EntityNotFoundException {
|
||||
return insuranceProviderRepository.findById(id)
|
||||
.orElseThrow(() -> new EntityNotFoundException("Insurance Provider with ID " + id + " not found."));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an existing insurance provider.
|
||||
*/
|
||||
@Override
|
||||
public InsuranceProvider updateInsuranceProvider(Long id, InsuranceProviderDTO updatedProviderDTO) throws EntityNotFoundException {
|
||||
InsuranceProvider existingProvider = getInsuranceProviderById(id);
|
||||
|
||||
if (updatedProviderDTO.providerName() != null) {
|
||||
existingProvider.setProviderName(updatedProviderDTO.providerName());
|
||||
}
|
||||
if (updatedProviderDTO.contactPerson() != null) {
|
||||
existingProvider.setContactPerson(updatedProviderDTO.contactPerson());
|
||||
}
|
||||
if (updatedProviderDTO.contactEmail() != null) {
|
||||
existingProvider.setContactEmail(updatedProviderDTO.contactEmail());
|
||||
}
|
||||
if (updatedProviderDTO.phoneNumber() != null) {
|
||||
existingProvider.setPhoneNumber(updatedProviderDTO.phoneNumber());
|
||||
}
|
||||
|
||||
return insuranceProviderRepository.save(existingProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an insurance provider from the database.
|
||||
*/
|
||||
@Override
|
||||
public void deleteInsuranceProvider(Long id) throws EntityNotFoundException {
|
||||
if (!insuranceProviderRepository.existsById(id)) {
|
||||
throw new EntityNotFoundException("Insurance Provider with ID " + id + " not found.");
|
||||
}
|
||||
insuranceProviderRepository.deleteById(id);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,149 @@
|
||||
package com.mirna.hospitalmanagementapi.application.services;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.application.usecase.inventory.FindInventoryItemByIdUseCase;
|
||||
import com.mirna.hospitalmanagementapi.application.usecase.inventory.SaveInventoryItemUseCase;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.inventory.InventoryItemDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.inventory.InventoryItemResponseDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.inventory.InventoryItem;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.inventory.InventoryItemType;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.inventory.InventorySupplier;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.inventory.InventoryItemRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.inventory.InventoryItemTypeRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.inventory.InventorySupplierRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.inventory.InventoryItemService;
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
public class InventoryItemServiceImpl implements InventoryItemService {
|
||||
|
||||
@Autowired
|
||||
private SaveInventoryItemUseCase saveInventoryItem;
|
||||
|
||||
@Autowired
|
||||
private FindInventoryItemByIdUseCase findInventoryItemById;
|
||||
|
||||
@Autowired
|
||||
private InventoryItemTypeRepository itemTypeRepository;
|
||||
|
||||
@Autowired
|
||||
private InventorySupplierRepository supplierRepository;
|
||||
|
||||
@Autowired
|
||||
private InventoryItemRepository inventoryItemRepository;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public InventoryItemResponseDTO addInventoryItem(InventoryItemDTO itemDTO) {
|
||||
InventoryItemType itemType = itemTypeRepository.findById(itemDTO.getItemTypeId())
|
||||
.orElseThrow(() -> new EntityNotFoundException("ไม่พบ Inventory Item Type ที่มี ID: " + itemDTO.getItemTypeId()));
|
||||
|
||||
InventorySupplier supplier = supplierRepository.findById(itemDTO.getSupplierId())
|
||||
.orElseThrow(() -> new EntityNotFoundException("ไม่พบ Inventory Supplier ที่มี ID: " + itemDTO.getSupplierId()));
|
||||
|
||||
InventoryItem item = new InventoryItem();
|
||||
item.setItemType(itemType);
|
||||
item.setSupplier(supplier);
|
||||
item.setItemName(itemDTO.getItemName());
|
||||
item.setDescription(itemDTO.getDescription());
|
||||
item.setCurrentStock(itemDTO.getCurrentStock() != null ? itemDTO.getCurrentStock() : 0);
|
||||
item.setUnitOfMeasure(itemDTO.getUnitOfMeasure());
|
||||
item.setUnitPrice(itemDTO.getUnitPrice());
|
||||
item.setReorderLevel(itemDTO.getReorderLevel() != null ? itemDTO.getReorderLevel() : 10);
|
||||
item.setExpirationDate(itemDTO.getExpirationDate());
|
||||
item.setLocation(itemDTO.getLocation());
|
||||
item.setIsActive(itemDTO.getIsActive() != null ? itemDTO.getIsActive() : true);
|
||||
item.setSerialNumber(itemDTO.getSerialNumber());
|
||||
item.setCreatedAt(ZonedDateTime.now());
|
||||
item.setUpdatedAt(ZonedDateTime.now());
|
||||
|
||||
InventoryItem savedItem = saveInventoryItem.execute(item);
|
||||
return new InventoryItemResponseDTO(savedItem);
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
@Override
|
||||
public InventoryItemResponseDTO getInventoryItemById(UUID id) {
|
||||
InventoryItem item = findInventoryItemById.execute(id);
|
||||
if (item == null) {
|
||||
throw new EntityNotFoundException("ไม่พบ Inventory item ที่มี ID: " + id);
|
||||
}
|
||||
return new InventoryItemResponseDTO(item);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public InventoryItemResponseDTO updateInventoryItem(UUID id, InventoryItemDTO itemDTO) throws EntityNotFoundException {
|
||||
InventoryItem item = findInventoryItemById.execute(id);
|
||||
if (item == null) {
|
||||
throw new EntityNotFoundException("ไม่พบ Inventory item ที่มี ID: " + id);
|
||||
}
|
||||
|
||||
if (itemDTO.getItemName() != null) {
|
||||
item.setItemName(itemDTO.getItemName());
|
||||
}
|
||||
if (itemDTO.getDescription() != null) {
|
||||
item.setDescription(itemDTO.getDescription());
|
||||
}
|
||||
if (itemDTO.getCurrentStock() != null) {
|
||||
item.setCurrentStock(itemDTO.getCurrentStock());
|
||||
}
|
||||
if (itemDTO.getUnitOfMeasure() != null) {
|
||||
item.setUnitOfMeasure(itemDTO.getUnitOfMeasure());
|
||||
}
|
||||
if (itemDTO.getUnitPrice() != null) {
|
||||
item.setUnitPrice(itemDTO.getUnitPrice());
|
||||
}
|
||||
if (itemDTO.getReorderLevel() != null) {
|
||||
item.setReorderLevel(itemDTO.getReorderLevel());
|
||||
}
|
||||
if (itemDTO.getExpirationDate() != null) {
|
||||
item.setExpirationDate(itemDTO.getExpirationDate());
|
||||
}
|
||||
if (itemDTO.getLocation() != null) {
|
||||
item.setLocation(itemDTO.getLocation());
|
||||
}
|
||||
if (itemDTO.getIsActive() != null) {
|
||||
item.setIsActive(itemDTO.getIsActive());
|
||||
}
|
||||
|
||||
item.setUpdatedAt(ZonedDateTime.now());
|
||||
|
||||
InventoryItem updatedItem = inventoryItemRepository.save(item);
|
||||
return new InventoryItemResponseDTO(updatedItem);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public void deleteInventoryItem(UUID id) throws EntityNotFoundException {
|
||||
InventoryItem item = findInventoryItemById.execute(id);
|
||||
if (item == null) {
|
||||
throw new EntityNotFoundException("ไม่พบ Inventory item ที่มี ID: " + id);
|
||||
}
|
||||
item.setIsActive(false);
|
||||
item.setUpdatedAt(ZonedDateTime.now());
|
||||
inventoryItemRepository.save(item);
|
||||
}
|
||||
|
||||
// เพิ่มเมธอดใหม่ที่ส่งค่ากลับเป็น Entity
|
||||
@Transactional(readOnly = true)
|
||||
@Override
|
||||
public InventoryItem findInventoryItemEntityById(UUID id) throws EntityNotFoundException {
|
||||
InventoryItem item = findInventoryItemById.execute(id);
|
||||
if (item == null) {
|
||||
throw new EntityNotFoundException("ไม่พบ Inventory item ที่มี ID: " + id);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
// เพิ่มเมธอดสำหรับบันทึก Entity โดยตรง
|
||||
@Transactional
|
||||
@Override
|
||||
public InventoryItem saveInventoryItemEntity(InventoryItem item) {
|
||||
return inventoryItemRepository.save(item);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
package com.mirna.hospitalmanagementapi.application.services;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.services.inventory.InventoryTransactionService;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.inventory.InventoryTransactionDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.inventory.InventoryTransactionResponseDTO; // Import DTO สำหรับ Response
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.inventory.InventoryItem;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.inventory.InventoryTransaction;
|
||||
import com.mirna.hospitalmanagementapi.domain.enums.TransactionType;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.inventory.InventoryItemRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.inventory.InventoryTransactionRepository;
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
public class InventoryTransactionServiceImpl implements InventoryTransactionService {
|
||||
|
||||
@Autowired
|
||||
private InventoryTransactionRepository transactionRepository;
|
||||
|
||||
@Autowired
|
||||
private InventoryItemRepository itemRepository;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public InventoryTransactionResponseDTO addTransaction(InventoryTransactionDTO transactionDTO) {
|
||||
InventoryItem item = itemRepository.findById(transactionDTO.getItemId())
|
||||
.orElseThrow(() -> new EntityNotFoundException("Inventory item with ID " + transactionDTO.getItemId() + " not found."));
|
||||
|
||||
InventoryTransaction transaction = new InventoryTransaction();
|
||||
transaction.setItem(item);
|
||||
transaction.setTransactionType(transactionDTO.getTransactionType());
|
||||
transaction.setQuantity(transactionDTO.getQuantity());
|
||||
transaction.setRelatedDocumentId(transactionDTO.getRelatedDocumentId());
|
||||
transaction.setNotes(transactionDTO.getNotes());
|
||||
transaction.setTransactionDate(ZonedDateTime.now());
|
||||
|
||||
// Update the stock count of the inventory item
|
||||
if (transactionDTO.getTransactionType() == TransactionType.IN) {
|
||||
item.setCurrentStock(item.getCurrentStock() + transactionDTO.getQuantity());
|
||||
} else if (transactionDTO.getTransactionType() == TransactionType.OUT) {
|
||||
if (item.getCurrentStock() < transactionDTO.getQuantity()) {
|
||||
throw new IllegalArgumentException("Quantity to be withdrawn is more than available stock.");
|
||||
}
|
||||
item.setCurrentStock(item.getCurrentStock() - transactionDTO.getQuantity());
|
||||
}
|
||||
itemRepository.save(item);
|
||||
|
||||
// Save transaction and return the response DTO
|
||||
InventoryTransaction newTransaction = transactionRepository.save(transaction);
|
||||
|
||||
// แปลง Entity ที่ถูกบันทึกแล้วให้เป็น DTO ก่อน return
|
||||
return new InventoryTransactionResponseDTO(newTransaction);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package com.mirna.hospitalmanagementapi.application.services;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.inventory.ItemTypeDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.inventory.InventoryItemType;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.inventory.InventoryItemTypeRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.inventory.ItemTypeService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class ItemTypeServiceImpl implements ItemTypeService {
|
||||
|
||||
@Autowired
|
||||
private InventoryItemTypeRepository inventoryItemTypeRepository;
|
||||
|
||||
@Override
|
||||
public InventoryItemType addItemType(ItemTypeDTO itemTypeDTO) {
|
||||
InventoryItemType newItemType = new InventoryItemType(itemTypeDTO);
|
||||
return inventoryItemTypeRepository.save(newItemType);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
package com.mirna.hospitalmanagementapi.application.services;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.LabResultDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.LabResult;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.MedicalRecord;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.LabResultRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.MedicalRecordRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.LabResultService;
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
public class LabResultServiceImpl implements LabResultService {
|
||||
|
||||
@Autowired
|
||||
private LabResultRepository labResultRepository;
|
||||
|
||||
@Autowired
|
||||
private MedicalRecordRepository medicalRecordRepository;
|
||||
|
||||
@Override
|
||||
public LabResult addLabResult(Long medicalRecordId, LabResultDTO labResultDTO) {
|
||||
MedicalRecord medicalRecord = medicalRecordRepository.findById(medicalRecordId)
|
||||
.orElseThrow(() -> new EntityNotFoundException("ไม่พบบันทึกทางการแพทย์ที่มี ID นี้"));
|
||||
|
||||
LabResult labResult = new LabResult();
|
||||
labResult.setMedicalRecord(medicalRecord);
|
||||
labResult.setTestName(labResultDTO.getTestName());
|
||||
labResult.setResultValue(labResultDTO.getResultValue());
|
||||
labResult.setUnit(labResultDTO.getUnit());
|
||||
labResult.setReferenceRange(labResultDTO.getReferenceRange());
|
||||
labResult.setStatus(labResultDTO.getStatus());
|
||||
labResult.setResultDate(LocalDateTime.now());
|
||||
|
||||
return labResultRepository.save(labResult);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LabResult getLabResultById(UUID id) {
|
||||
return labResultRepository.findById(id)
|
||||
.orElseThrow(() -> new EntityNotFoundException("ไม่พบผลแล็บที่มี ID นี้"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOwner(UUID labResultId, Long currentUserId) {
|
||||
return labResultRepository.findById(labResultId)
|
||||
.map(labResult -> labResult.getMedicalRecord().getPatient().getUser().getId().equals(currentUserId))
|
||||
.orElse(false);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,71 @@
|
||||
package com.mirna.hospitalmanagementapi.application.services;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.MedicalEquipmentScheduleDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.inventory.InventoryItem;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.MedicalEquipmentSchedule;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.inventory.InventoryItemRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.MedicalEquipmentScheduleRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.MedicalEquipmentScheduleService;
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.MedicalEquipmentScheduleResponseDTO;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
public class MedicalEquipmentScheduleServiceImpl implements MedicalEquipmentScheduleService {
|
||||
|
||||
@Autowired
|
||||
private MedicalEquipmentScheduleRepository medicalEquipmentScheduleRepository;
|
||||
|
||||
@Autowired
|
||||
private InventoryItemRepository inventoryItemRepository;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public MedicalEquipmentScheduleResponseDTO addMedicalEquipmentSchedule(MedicalEquipmentScheduleDTO medicalEquipmentScheduleDTO) {
|
||||
InventoryItem equipment = inventoryItemRepository.findById(medicalEquipmentScheduleDTO.equipmentId())
|
||||
.orElseThrow(() -> new EntityNotFoundException("Medical equipment with ID " + medicalEquipmentScheduleDTO.equipmentId() + " not found."));
|
||||
|
||||
LocalDateTime startTime = medicalEquipmentScheduleDTO.startTime();
|
||||
LocalDateTime endTime = medicalEquipmentScheduleDTO.endTime();
|
||||
|
||||
List<MedicalEquipmentSchedule> existingSchedules = medicalEquipmentScheduleRepository.findByInventoryItemAndEndTimeAfterAndStartTimeBefore(
|
||||
equipment,
|
||||
startTime,
|
||||
endTime
|
||||
);
|
||||
|
||||
if (!existingSchedules.isEmpty()) {
|
||||
throw new IllegalArgumentException("Conflict: The medical equipment is already scheduled during this time slot.");
|
||||
}
|
||||
|
||||
MedicalEquipmentSchedule newSchedule = new MedicalEquipmentSchedule();
|
||||
newSchedule.setInventoryItem(equipment);
|
||||
newSchedule.setStartTime(startTime);
|
||||
newSchedule.setEndTime(endTime);
|
||||
|
||||
MedicalEquipmentSchedule savedSchedule = medicalEquipmentScheduleRepository.save(newSchedule);
|
||||
|
||||
return new MedicalEquipmentScheduleResponseDTO(savedSchedule);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MedicalEquipmentScheduleResponseDTO getMedicalEquipmentScheduleById(Long id) throws EntityNotFoundException {
|
||||
MedicalEquipmentSchedule schedule = medicalEquipmentScheduleRepository.findById(id)
|
||||
.orElseThrow(() -> new EntityNotFoundException("Medical equipment schedule with ID " + id + " not found."));
|
||||
return new MedicalEquipmentScheduleResponseDTO(schedule);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<MedicalEquipmentScheduleResponseDTO> getAllMedicalEquipmentSchedules(Pageable pageable) {
|
||||
Page<MedicalEquipmentSchedule> schedulesPage = medicalEquipmentScheduleRepository.findAll(pageable);
|
||||
return schedulesPage.map(MedicalEquipmentScheduleResponseDTO::new);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,108 @@
|
||||
package com.mirna.hospitalmanagementapi.application.services;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.MedicalImage;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.MedicalRecord;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.MedicalImageRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.MedicalRecordRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.MedicalImageService;
|
||||
import io.minio.*;
|
||||
import io.minio.errors.MinioException;
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.core.io.InputStreamResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import java.io.InputStream;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
public class MedicalImageServiceImpl implements MedicalImageService {
|
||||
|
||||
@Autowired
|
||||
private MinioClient minioClient;
|
||||
|
||||
// เพิ่ม repository สำหรับการจัดการข้อมูลในฐานข้อมูล
|
||||
@Autowired
|
||||
private MedicalImageRepository medicalImageRepository;
|
||||
|
||||
@Autowired
|
||||
private MedicalRecordRepository medicalRecordRepository;
|
||||
|
||||
@Value("${minio.bucket-name}")
|
||||
private String bucketName;
|
||||
|
||||
@Override
|
||||
public MedicalImage uploadImage(Long medicalRecordId, MultipartFile file, String imageType, String notes) {
|
||||
try {
|
||||
// ค้นหา MedicalRecord ที่ต้องการเชื่อมโยง
|
||||
MedicalRecord medicalRecord = medicalRecordRepository.findById(medicalRecordId)
|
||||
.orElseThrow(() -> new EntityNotFoundException("Medical Record not found."));
|
||||
|
||||
// สร้าง bucket ถ้ายังไม่มี (โค้ดเดิม)
|
||||
if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {
|
||||
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
|
||||
}
|
||||
|
||||
// สร้างชื่อไฟล์ที่ไม่ซ้ำกัน
|
||||
String fileName = UUID.randomUUID().toString() + "-" + file.getOriginalFilename();
|
||||
InputStream inputStream = file.getInputStream();
|
||||
|
||||
// อัปโหลดไฟล์ไปยัง MinIO (โค้ดเดิม)
|
||||
minioClient.putObject(
|
||||
PutObjectArgs.builder()
|
||||
.bucket(bucketName)
|
||||
.object(fileName)
|
||||
.stream(inputStream, file.getSize(), -1)
|
||||
.contentType(file.getContentType())
|
||||
.build()
|
||||
);
|
||||
|
||||
// บันทึกข้อมูล MedicalImage ลงในฐานข้อมูล
|
||||
MedicalImage medicalImage = new MedicalImage();
|
||||
medicalImage.setMedicalRecord(medicalRecord);
|
||||
medicalImage.setFileName(fileName);
|
||||
medicalImage.setImageType(imageType);
|
||||
medicalImage.setNotes(notes);
|
||||
medicalImage.setUploadDate(LocalDateTime.now());
|
||||
|
||||
return medicalImageRepository.save(medicalImage);
|
||||
|
||||
} catch (MinioException e) {
|
||||
throw new RuntimeException("MinIO Error: " + e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Error uploading file: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resource downloadImage(UUID id) {
|
||||
try {
|
||||
// ค้นหา MedicalImage จาก ID ในฐานข้อมูล
|
||||
MedicalImage medicalImage = medicalImageRepository.findById(id)
|
||||
.orElseThrow(() -> new EntityNotFoundException("Medical Image not found."));
|
||||
|
||||
// ดาวน์โหลดไฟล์จาก MinIO โดยใช้ชื่อไฟล์จากฐานข้อมูล
|
||||
InputStream stream = minioClient.getObject(
|
||||
GetObjectArgs.builder()
|
||||
.bucket(bucketName)
|
||||
.object(medicalImage.getFileName())
|
||||
.build()
|
||||
);
|
||||
return new InputStreamResource(stream);
|
||||
} catch (MinioException e) {
|
||||
throw new RuntimeException("MinIO Error: " + e.getMessage());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Error downloading file: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOwner(UUID medicalImageId, Long currentUserId) {
|
||||
return medicalImageRepository.findById(medicalImageId)
|
||||
.map(medicalImage -> medicalImage.getMedicalRecord().getPatient().getUser().getId().equals(currentUserId))
|
||||
.orElse(false);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,139 @@
|
||||
package com.mirna.hospitalmanagementapi.application.services;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.application.usecase.medicalrecord.FindMedicalRecordByIdUseCase;
|
||||
import com.mirna.hospitalmanagementapi.application.usecase.medicalrecord.SaveMedicalRecordUseCase;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.MedicalRecordDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.Doctor;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.MedicalRecord;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.Patient;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.MedicalRecordRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.DoctorService;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.MedicalRecordService;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.PatientService;
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* คลาสนี้เป็น Implementation ของ interface MedicalRecordService
|
||||
*
|
||||
* คลาสนี้จะให้บริการเมธอดสำหรับดำเนินการกับข้อมูลบันทึกทางการแพทย์
|
||||
*
|
||||
* @author FlookSP
|
||||
* @version 1.0
|
||||
*/
|
||||
@Service
|
||||
public class MedicalRecordServiceImpl implements MedicalRecordService {
|
||||
|
||||
@Autowired
|
||||
private SaveMedicalRecordUseCase saveMedicalRecord;
|
||||
|
||||
@Autowired
|
||||
private FindMedicalRecordByIdUseCase findMedicalRecordById;
|
||||
|
||||
@Autowired
|
||||
private PatientService patientService;
|
||||
|
||||
@Autowired
|
||||
private DoctorService doctorService;
|
||||
|
||||
@Autowired
|
||||
private MedicalRecordRepository medicalRecordRepository;
|
||||
|
||||
/**
|
||||
* เพิ่มบันทึกทางการแพทย์ใหม่ในฐานข้อมูล
|
||||
*/
|
||||
@Override
|
||||
public MedicalRecord addMedicalRecord(MedicalRecordDTO medicalRecordDTO) throws EntityNotFoundException {
|
||||
Patient patient = patientService.findPatientById(medicalRecordDTO.getPatientId());
|
||||
Doctor doctor = doctorService.findDoctorById(medicalRecordDTO.getDoctorId());
|
||||
|
||||
MedicalRecord medicalRecord = new MedicalRecord(
|
||||
patient,
|
||||
doctor,
|
||||
null,
|
||||
medicalRecordDTO.getDiagnosis(),
|
||||
medicalRecordDTO.getTreatment(),
|
||||
medicalRecordDTO.getNotes()
|
||||
);
|
||||
|
||||
return saveMedicalRecord.execute(medicalRecord);
|
||||
}
|
||||
|
||||
/**
|
||||
* ค้นหาบันทึกทางการแพทย์จาก ID (ไม่รวมรายละเอียดเพิ่มเติม)
|
||||
*/
|
||||
@Override
|
||||
public MedicalRecord getMedicalRecordById(Long id) throws EntityNotFoundException {
|
||||
MedicalRecord medicalRecord = findMedicalRecordById.execute(id);
|
||||
|
||||
if (medicalRecord == null) {
|
||||
throw new EntityNotFoundException("ไม่พบบันทึกทางการแพทย์ที่มี ID นี้");
|
||||
}
|
||||
|
||||
return medicalRecord;
|
||||
}
|
||||
|
||||
/**
|
||||
* ค้นหาบันทึกทางการแพทย์จาก ID พร้อมรายละเอียดทั้งหมด (รูปภาพ, ผลแล็บ, ฯลฯ)
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public MedicalRecord getMedicalRecordDetails(Long id) throws EntityNotFoundException {
|
||||
MedicalRecord medicalRecord = medicalRecordRepository.findById(id)
|
||||
.orElseThrow(() -> new EntityNotFoundException("ไม่พบบันทึกทางการแพทย์ที่มี ID นี้"));
|
||||
|
||||
// หากใช้ Lazy Loading การเรียกเมธอดเหล่านี้จะบังคับให้โหลดข้อมูลที่เกี่ยวข้อง
|
||||
// โดยอัตโนมัติภายใต้ @Transactional
|
||||
medicalRecord.getMedicalImages().size();
|
||||
medicalRecord.getLabResults().size();
|
||||
|
||||
return medicalRecord;
|
||||
}
|
||||
|
||||
/**
|
||||
* อัปเดตบันทึกทางการแพทย์ที่มีอยู่จาก ID
|
||||
*/
|
||||
@Override
|
||||
public MedicalRecord updateMedicalRecord(Long id, MedicalRecordDTO medicalRecordDTO) throws EntityNotFoundException {
|
||||
MedicalRecord medicalRecord = findMedicalRecordById.execute(id);
|
||||
|
||||
if (medicalRecord == null) {
|
||||
throw new EntityNotFoundException("ไม่พบบันทึกทางการแพทย์ที่มี ID นี้");
|
||||
}
|
||||
|
||||
if (medicalRecordDTO.getDiagnosis() != null) {
|
||||
medicalRecord.setDiagnosis(medicalRecordDTO.getDiagnosis());
|
||||
}
|
||||
if (medicalRecordDTO.getTreatment() != null) {
|
||||
medicalRecord.setTreatment(medicalRecordDTO.getTreatment());
|
||||
}
|
||||
if (medicalRecordDTO.getNotes() != null) {
|
||||
medicalRecord.setNotes(medicalRecordDTO.getNotes());
|
||||
}
|
||||
|
||||
return saveMedicalRecord.execute(medicalRecord);
|
||||
}
|
||||
|
||||
/**
|
||||
* ลบบันทึกทางการแพทย์จาก ID
|
||||
*/
|
||||
@Override
|
||||
public void deleteMedicalRecord(Long id) throws EntityNotFoundException {
|
||||
MedicalRecord medicalRecord = findMedicalRecordById.execute(id);
|
||||
|
||||
if (medicalRecord == null) {
|
||||
throw new EntityNotFoundException("ไม่พบบันทึกทางการแพทย์ที่มี ID นี้");
|
||||
}
|
||||
|
||||
medicalRecordRepository.delete(medicalRecord);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOwner(Long medicalRecordId, Long patientId) {
|
||||
return medicalRecordRepository.findById(medicalRecordId)
|
||||
.map(medicalRecord -> medicalRecord.getPatient().getId().equals(patientId))
|
||||
.orElse(false);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,78 @@
|
||||
package com.mirna.hospitalmanagementapi.application.services;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.NurseScheduleDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.Nurse;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.NurseSchedule;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.NurseRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.NurseScheduleRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.NurseScheduleService;
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class NurseScheduleServiceImpl implements NurseScheduleService {
|
||||
|
||||
@Autowired
|
||||
private NurseScheduleRepository nurseScheduleRepository;
|
||||
|
||||
@Autowired
|
||||
private NurseRepository nurseRepository;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public NurseSchedule addNurseSchedule(NurseScheduleDTO nurseScheduleDTO) {
|
||||
Nurse nurse = nurseRepository.findById(nurseScheduleDTO.nurseId())
|
||||
.orElseThrow(() -> new EntityNotFoundException("Nurse with ID " + nurseScheduleDTO.nurseId() + " not found."));
|
||||
|
||||
LocalDateTime startTime = nurseScheduleDTO.startTime();
|
||||
LocalDateTime endTime = nurseScheduleDTO.endTime();
|
||||
|
||||
// 1. ตรวจสอบความขัดแย้งของเวลา
|
||||
List<NurseSchedule> existingSchedules = nurseScheduleRepository.findOverlappingSchedules(
|
||||
nurse.getId(),
|
||||
startTime,
|
||||
endTime
|
||||
);
|
||||
|
||||
if (!existingSchedules.isEmpty()) {
|
||||
throw new IllegalArgumentException("Conflict: The nurse is already scheduled during this time slot.");
|
||||
}
|
||||
|
||||
// 2. ตรวจสอบเวลาพักผ่อนขั้นต่ำ (สมมติว่ากำหนดไว้ 8 ชั่วโมง)
|
||||
// ค้นหากะล่าสุดของพยาบาลคนนี้
|
||||
nurseScheduleRepository.findTopByNurseIdOrderByEndTimeDesc(nurse.getId())
|
||||
.ifPresent(lastSchedule -> {
|
||||
// คำนวณเวลาเริ่มต้นของกะใหม่ (startTime) จากเวลาสิ้นสุดของกะล่าสุด (endTime) บวกเวลาพักผ่อนขั้นต่ำ
|
||||
LocalDateTime nextAvailableTime = lastSchedule.getEndTime().plusHours(8); // กำหนดเวลาพักผ่อน 8 ชั่วโมง
|
||||
if (startTime.isBefore(nextAvailableTime)) {
|
||||
throw new IllegalArgumentException("Conflict: The nurse must have at least 8 hours of rest between shifts.");
|
||||
}
|
||||
});
|
||||
|
||||
// 3. ถ้าไม่มีข้อผิดพลาด ให้สร้างตารางเวรใหม่
|
||||
NurseSchedule newSchedule = new NurseSchedule();
|
||||
newSchedule.setNurse(nurse);
|
||||
newSchedule.setStartTime(startTime);
|
||||
newSchedule.setEndTime(endTime);
|
||||
|
||||
return nurseScheduleRepository.save(newSchedule);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NurseSchedule getNurseScheduleById(Long id) throws EntityNotFoundException {
|
||||
return nurseScheduleRepository.findById(id)
|
||||
.orElseThrow(() -> new EntityNotFoundException("Nurse schedule with ID " + id + " not found."));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<NurseSchedule> getAllNurseSchedules(Pageable pageable) {
|
||||
return nurseScheduleRepository.findAll(pageable);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,75 @@
|
||||
package com.mirna.hospitalmanagementapi.application.services;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.NurseDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.Nurse;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.NurseRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.NurseService;
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
public class NurseServiceImpl implements NurseService {
|
||||
|
||||
@Autowired
|
||||
private NurseRepository nurseRepository;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Nurse addNurse(NurseDTO nurseDTO) {
|
||||
Nurse nurse = new Nurse();
|
||||
nurse.setName(nurseDTO.name());
|
||||
nurse.setLicenseNumber(nurseDTO.licenseNumber());
|
||||
nurse.setEmail(nurseDTO.email());
|
||||
nurse.setTelephone(nurseDTO.telephone());
|
||||
nurse.setShiftType(nurseDTO.shiftType());
|
||||
return nurseRepository.save(nurse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Nurse getNurseById(Long id) throws EntityNotFoundException {
|
||||
return nurseRepository.findById(id)
|
||||
.orElseThrow(() -> new EntityNotFoundException("Nurse with ID " + id + " not found."));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<Nurse> getAllNurses(Pageable pageable) {
|
||||
return nurseRepository.findAll(pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Nurse updateNurse(Long id, NurseDTO nurseDTO) throws EntityNotFoundException {
|
||||
Nurse existingNurse = getNurseById(id);
|
||||
|
||||
if (nurseDTO.name() != null) {
|
||||
existingNurse.setName(nurseDTO.name());
|
||||
}
|
||||
if (nurseDTO.licenseNumber() != null) {
|
||||
existingNurse.setLicenseNumber(nurseDTO.licenseNumber());
|
||||
}
|
||||
if (nurseDTO.email() != null) {
|
||||
existingNurse.setEmail(nurseDTO.email());
|
||||
}
|
||||
if (nurseDTO.telephone() != null) {
|
||||
existingNurse.setTelephone(nurseDTO.telephone());
|
||||
}
|
||||
if (nurseDTO.shiftType() != null) {
|
||||
existingNurse.setShiftType(nurseDTO.shiftType());
|
||||
}
|
||||
|
||||
return nurseRepository.save(existingNurse);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void deleteNurse(Long id) throws EntityNotFoundException {
|
||||
if (!nurseRepository.existsById(id)) {
|
||||
throw new EntityNotFoundException("Nurse with ID " + id + " not found.");
|
||||
}
|
||||
nurseRepository.deleteById(id);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,66 @@
|
||||
package com.mirna.hospitalmanagementapi.application.services;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.OperatingRoomScheduleDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.OperatingRoom;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.OperatingRoomSchedule;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.OperatingRoomRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.OperatingRoomScheduleRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.OperatingRoomScheduleService;
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class OperatingRoomScheduleServiceImpl implements OperatingRoomScheduleService {
|
||||
|
||||
@Autowired
|
||||
private OperatingRoomScheduleRepository operatingRoomScheduleRepository;
|
||||
|
||||
@Autowired
|
||||
private OperatingRoomRepository operatingRoomRepository;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public OperatingRoomSchedule addOperatingRoomSchedule(OperatingRoomScheduleDTO operatingRoomScheduleDTO) {
|
||||
OperatingRoom room = operatingRoomRepository.findById(operatingRoomScheduleDTO.roomId())
|
||||
.orElseThrow(() -> new EntityNotFoundException("Operating room with ID " + operatingRoomScheduleDTO.roomId() + " not found."));
|
||||
|
||||
LocalDateTime startTime = operatingRoomScheduleDTO.startTime();
|
||||
LocalDateTime endTime = operatingRoomScheduleDTO.endTime();
|
||||
|
||||
// ตรวจสอบความขัดแย้งของเวลา
|
||||
List<OperatingRoomSchedule> existingSchedules = operatingRoomScheduleRepository.findByOperatingRoomIdAndEndTimeAfterAndStartTimeBefore(
|
||||
room.getId(),
|
||||
startTime,
|
||||
endTime
|
||||
);
|
||||
|
||||
if (!existingSchedules.isEmpty()) {
|
||||
throw new IllegalArgumentException("Conflict: The operating room is already scheduled during this time slot.");
|
||||
}
|
||||
|
||||
OperatingRoomSchedule newSchedule = new OperatingRoomSchedule();
|
||||
newSchedule.setOperatingRoom(room);
|
||||
newSchedule.setStartTime(startTime);
|
||||
newSchedule.setEndTime(endTime);
|
||||
|
||||
return operatingRoomScheduleRepository.save(newSchedule);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OperatingRoomSchedule getOperatingRoomScheduleById(Long id) throws EntityNotFoundException {
|
||||
return operatingRoomScheduleRepository.findById(id)
|
||||
.orElseThrow(() -> new EntityNotFoundException("Operating room schedule with ID " + id + " not found."));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<OperatingRoomSchedule> getAllOperatingRoomSchedules(Pageable pageable) {
|
||||
return operatingRoomScheduleRepository.findAll(pageable);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
package com.mirna.hospitalmanagementapi.application.services;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.OperatingRoomDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.OperatingRoom;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.OperatingRoomRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.OperatingRoomService;
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
public class OperatingRoomServiceImpl implements OperatingRoomService {
|
||||
|
||||
@Autowired
|
||||
private OperatingRoomRepository operatingRoomRepository;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public OperatingRoom addOperatingRoom(OperatingRoomDTO operatingRoomDTO) {
|
||||
OperatingRoom room = new OperatingRoom();
|
||||
room.setRoomNumber(operatingRoomDTO.roomNumber());
|
||||
room.setAvailable(operatingRoomDTO.isAvailable());
|
||||
return operatingRoomRepository.save(room);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OperatingRoom getOperatingRoomById(Long id) throws EntityNotFoundException {
|
||||
return operatingRoomRepository.findById(id)
|
||||
.orElseThrow(() -> new EntityNotFoundException("Operating Room with ID " + id + " not found."));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<OperatingRoom> getAllOperatingRooms(Pageable pageable) {
|
||||
return operatingRoomRepository.findAll(pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public OperatingRoom updateOperatingRoom(Long id, OperatingRoomDTO operatingRoomDTO) throws EntityNotFoundException {
|
||||
OperatingRoom existingRoom = getOperatingRoomById(id);
|
||||
|
||||
if (operatingRoomDTO.roomNumber() != null) {
|
||||
existingRoom.setRoomNumber(operatingRoomDTO.roomNumber());
|
||||
}
|
||||
if (operatingRoomDTO.isAvailable() != null) {
|
||||
existingRoom.setAvailable(operatingRoomDTO.isAvailable());
|
||||
}
|
||||
|
||||
return operatingRoomRepository.save(existingRoom);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void deleteOperatingRoom(Long id) throws EntityNotFoundException {
|
||||
if (!operatingRoomRepository.existsById(id)) {
|
||||
throw new EntityNotFoundException("Operating Room with ID " + id + " not found.");
|
||||
}
|
||||
operatingRoomRepository.deleteById(id);
|
||||
}
|
||||
}
|
||||
@ -4,6 +4,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.application.usecase.patient.FindPatientByIdUseCase;
|
||||
import com.mirna.hospitalmanagementapi.application.usecase.patient.FindPatientsUseCase;
|
||||
@ -15,6 +16,11 @@ import com.mirna.hospitalmanagementapi.domain.dtos.patient.PatientUpdatedDataDTO
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.Address;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.Patient;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.PatientService;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.auth.LinkPatientToUserDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.auth.User;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.auth.UserRepository;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import com.mirna.hospitalmanagementapi.domain.enums.Role;
|
||||
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
|
||||
@ -29,136 +35,177 @@ import jakarta.persistence.EntityNotFoundException;
|
||||
@Service
|
||||
public class PatientServiceImpl implements PatientService {
|
||||
|
||||
@Autowired
|
||||
private SavePatientUseCase savePatient;
|
||||
@Autowired
|
||||
private SavePatientUseCase savePatient;
|
||||
|
||||
@Autowired
|
||||
private FindPatientByIdUseCase findPatientById;
|
||||
@Autowired
|
||||
private FindPatientByIdUseCase findPatientById;
|
||||
|
||||
@Autowired
|
||||
private FindPatientsUseCase findPatients;
|
||||
@Autowired
|
||||
private FindPatientsUseCase findPatients;
|
||||
|
||||
/**
|
||||
* Adds a new patient to the database.
|
||||
*
|
||||
* @param patientDTO A data transfer object containing the data for Patient
|
||||
* entity.
|
||||
* @return The saved patient if successful, or null if there is an error.
|
||||
*/
|
||||
@Override
|
||||
public Patient addPatient(PatientDTO patientDTO) {
|
||||
Patient patient = new Patient(patientDTO);
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
@Autowired
|
||||
private BCryptPasswordEncoder passwordEncoder;
|
||||
|
||||
return this.savePatient.execute(patient);
|
||||
}
|
||||
/**
|
||||
* Adds a new patient to the database.
|
||||
*
|
||||
* @param patientDTO A data transfer object containing the data for Patient
|
||||
* entity.
|
||||
* @return The saved patient if successful, or null if there is an error.
|
||||
*/
|
||||
@Override
|
||||
public Patient addPatient(PatientDTO patientDTO) {
|
||||
Patient patient = new Patient(patientDTO);
|
||||
|
||||
/**
|
||||
* Finds a stored patient by id.
|
||||
*
|
||||
* @param id A long representing the patient's unique identifier
|
||||
* @return The corresponding patient if successful, or throws an EntityNotFoundException if it is
|
||||
* non-existent.
|
||||
* @throws EntityNotFoundException When patient with id provided is non-existent
|
||||
*/
|
||||
@Override
|
||||
public Patient findPatientById(Long id) throws EntityNotFoundException {
|
||||
Patient patient = this.findPatientById.execute(id);
|
||||
return this.savePatient.execute(patient);
|
||||
}
|
||||
|
||||
if (patient == null) throw new EntityNotFoundException("No existing patient with this id");
|
||||
/**
|
||||
* Finds a stored patient by id.
|
||||
* * @param id A long representing the patient's unique identifier
|
||||
* @return The corresponding patient if successful, or throws an EntityNotFoundException if it is
|
||||
* non-existent.
|
||||
* @throws EntityNotFoundException When patient with id provided is non-existent
|
||||
*/
|
||||
@Override
|
||||
public Patient findPatientById(Long id) throws EntityNotFoundException {
|
||||
Patient patient = this.findPatientById.execute(id);
|
||||
|
||||
return patient;
|
||||
}
|
||||
if (patient == null) throw new EntityNotFoundException("No existing patient with this id");
|
||||
|
||||
/**
|
||||
* Finds patients from the database.
|
||||
*
|
||||
* @param pageable Pagination information, such as size and page number
|
||||
*
|
||||
* @return A paginated sublist containing data transfer objects with patients public information in the repository
|
||||
*/
|
||||
@Override
|
||||
public Page<PatientPublicDataDTO> findPatients(Pageable pageable) {
|
||||
return findPatients.execute(pageable).map(PatientPublicDataDTO::new);
|
||||
}
|
||||
return patient;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Finds patients from the database.
|
||||
*
|
||||
* @param pageable Pagination information, such as size and page number
|
||||
* * @return A paginated sublist containing data transfer objects with patients public information in the repository
|
||||
*/
|
||||
@Override
|
||||
public Page<PatientPublicDataDTO> findPatients(Pageable pageable) {
|
||||
return findPatients.execute(pageable).map(PatientPublicDataDTO::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an existing patient record
|
||||
* @param patientUpdatedDataDTO Data transfer object containing the patient updated data along with their corresponding id
|
||||
*
|
||||
* @return The updated patient if successful, or null if there is an error.
|
||||
*/
|
||||
@Override
|
||||
public Patient updatePatient(PatientUpdatedDataDTO patientUpdatedDataDTO) {
|
||||
* * @return The updated patient if successful, or null if there is an error.
|
||||
*/
|
||||
@Override
|
||||
public Patient updatePatient(PatientUpdatedDataDTO patientUpdatedDataDTO) {
|
||||
|
||||
Patient patient = findPatientById.execute(patientUpdatedDataDTO.id());
|
||||
Patient patient = findPatientById.execute(patientUpdatedDataDTO.id());
|
||||
|
||||
if (patient == null) throw new EntityNotFoundException("No existing patient with this id");
|
||||
if (patient == null) throw new EntityNotFoundException("No existing patient with this id");
|
||||
|
||||
if (patientUpdatedDataDTO.name() != null) patient.setName(patientUpdatedDataDTO.name());
|
||||
if (patientUpdatedDataDTO.name() != null) patient.setName(patientUpdatedDataDTO.name());
|
||||
|
||||
if (patientUpdatedDataDTO.telephone() != null) patient.setTelephone(patientUpdatedDataDTO.telephone());
|
||||
if (patientUpdatedDataDTO.telephone() != null) patient.setTelephone(patientUpdatedDataDTO.telephone());
|
||||
|
||||
if (patientUpdatedDataDTO.address() != null) {
|
||||
if (patientUpdatedDataDTO.address() != null) {
|
||||
|
||||
AddressDTO addressUpdatedDataDTO = patientUpdatedDataDTO.address();
|
||||
Address address = patient.getAddress();
|
||||
AddressDTO addressUpdatedDataDTO = patientUpdatedDataDTO.address();
|
||||
Address address = patient.getAddress();
|
||||
|
||||
if (addressUpdatedDataDTO.street() != null) {
|
||||
address.setStreet(addressUpdatedDataDTO.street());
|
||||
}
|
||||
if (addressUpdatedDataDTO.street() != null) {
|
||||
address.setStreet(addressUpdatedDataDTO.street());
|
||||
}
|
||||
|
||||
if (addressUpdatedDataDTO.neighborhood() != null) {
|
||||
address.setNeighborhood(addressUpdatedDataDTO.neighborhood());
|
||||
}
|
||||
if (addressUpdatedDataDTO.neighborhood() != null) {
|
||||
address.setNeighborhood(addressUpdatedDataDTO.neighborhood());
|
||||
}
|
||||
|
||||
if (addressUpdatedDataDTO.city() != null) {
|
||||
address.setCity(addressUpdatedDataDTO.city());
|
||||
}
|
||||
if (addressUpdatedDataDTO.city() != null) {
|
||||
address.setCity(addressUpdatedDataDTO.city());
|
||||
}
|
||||
|
||||
if (addressUpdatedDataDTO.zipCode() != null) {
|
||||
address.setZipCode(addressUpdatedDataDTO.zipCode());
|
||||
}
|
||||
if (addressUpdatedDataDTO.zipCode() != null) {
|
||||
address.setZipCode(addressUpdatedDataDTO.zipCode());
|
||||
}
|
||||
|
||||
if (addressUpdatedDataDTO.state() != null) {
|
||||
address.setState(addressUpdatedDataDTO.state());
|
||||
}
|
||||
if (addressUpdatedDataDTO.state() != null) {
|
||||
address.setState(addressUpdatedDataDTO.state());
|
||||
}
|
||||
|
||||
if (addressUpdatedDataDTO.additionalDetails() != null) {
|
||||
address.setAdditionalDetails(addressUpdatedDataDTO.additionalDetails());
|
||||
}
|
||||
if (addressUpdatedDataDTO.additionalDetails() != null) {
|
||||
address.setAdditionalDetails(addressUpdatedDataDTO.additionalDetails());
|
||||
}
|
||||
|
||||
if (addressUpdatedDataDTO.houseNumber() != null) {
|
||||
address.setHouseNumber(addressUpdatedDataDTO.houseNumber());
|
||||
}
|
||||
if (addressUpdatedDataDTO.houseNumber() != null) {
|
||||
address.setHouseNumber(addressUpdatedDataDTO.houseNumber());
|
||||
}
|
||||
|
||||
patient.setAddress(address);
|
||||
}
|
||||
patient.setAddress(address);
|
||||
}
|
||||
|
||||
patient = savePatient.execute(patient);
|
||||
patient = savePatient.execute(patient);
|
||||
|
||||
return patient;
|
||||
}
|
||||
return patient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deactivates an existing patient record by provided id
|
||||
*
|
||||
* @param id Long that represents the patient's unique identifier
|
||||
*
|
||||
* @return The deactivated patient if successful, or throws an
|
||||
* EntityNotFoundException if it is non-existent.
|
||||
* @throws EntityNotFoundException When patient with id provided is non-existent
|
||||
*/
|
||||
@Override
|
||||
public Patient deactivatePatient(Long id) throws EntityNotFoundException {
|
||||
Patient patient = findPatientById.execute(id);
|
||||
/**
|
||||
* Deactivates an existing patient record by provided id
|
||||
* * @param id Long that represents the patient's unique identifier
|
||||
* * @return The deactivated patient if successful, or throws an
|
||||
* EntityNotFoundException if it is non-existent.
|
||||
* @throws EntityNotFoundException When patient with id provided is non-existent
|
||||
*/
|
||||
@Override
|
||||
public Patient deactivatePatient(Long id) throws EntityNotFoundException {
|
||||
Patient patient = findPatientById.execute(id);
|
||||
|
||||
if (patient == null) {
|
||||
throw new EntityNotFoundException("No existing patient with this id");
|
||||
}
|
||||
if (patient == null) {
|
||||
throw new EntityNotFoundException("No existing patient with this id");
|
||||
}
|
||||
|
||||
patient.setActive(false);
|
||||
patient.setActive(false);
|
||||
|
||||
return savePatient.execute(patient);
|
||||
}
|
||||
return savePatient.execute(patient);
|
||||
}
|
||||
|
||||
/**
|
||||
* Links an existing patient record to a new user account
|
||||
*
|
||||
* @param linkPatientToUserDTO Data transfer object containing the patient's ID, new username, password, and CPF
|
||||
*
|
||||
* @return The updated patient if successful
|
||||
* @throws EntityNotFoundException If the patient is not found
|
||||
* @throws IllegalArgumentException If the patient is already linked or CPF does not match
|
||||
*/
|
||||
@Transactional
|
||||
public Patient linkPatientToUser(LinkPatientToUserDTO linkPatientToUserDTO) {
|
||||
|
||||
// 1. ตรวจสอบว่า patientId มีอยู่ในระบบจริงหรือไม่
|
||||
Patient patient = findPatientById.execute(linkPatientToUserDTO.patientId());
|
||||
|
||||
if (patient == null) {
|
||||
throw new EntityNotFoundException("Patient not found with ID: " + linkPatientToUserDTO.patientId());
|
||||
}
|
||||
|
||||
// 2. ตรวจสอบว่าผู้ป่วยยังไม่ได้ถูกผูกกับบัญชีผู้ใช้
|
||||
if (patient.getUser() != null) {
|
||||
throw new IllegalArgumentException("Patient is already linked to a user account.");
|
||||
}
|
||||
|
||||
// 3. ตรวจสอบ CPF เพื่อยืนยันตัวตน
|
||||
if (!patient.getCpf().equals(linkPatientToUserDTO.cpf())) {
|
||||
throw new IllegalArgumentException("Invalid CPF for the given patient.");
|
||||
}
|
||||
|
||||
// 4. สร้างบัญชีผู้ใช้ใหม่
|
||||
User newUser = new User();
|
||||
newUser.setLogin(linkPatientToUserDTO.username());
|
||||
newUser.setPassword(passwordEncoder.encode(linkPatientToUserDTO.password()));
|
||||
// ตั้งค่าบทบาท (Role)
|
||||
newUser.setRole(Role.ROLE_PATIENT);
|
||||
User savedUser = userRepository.save(newUser);
|
||||
|
||||
// 5. อัปเดตข้อมูลผู้ป่วยด้วย ID ของผู้ใช้ใหม่
|
||||
patient.setUser(savedUser);
|
||||
return savePatient.execute(patient);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
package com.mirna.hospitalmanagementapi.application.services;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.PaymentDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.Payment;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.PaymentRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.PaymentService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.services.ConsultationService;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.MedicalRecordService;
|
||||
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class PaymentServiceImpl implements PaymentService {
|
||||
|
||||
@Autowired
|
||||
private PaymentRepository paymentRepository;
|
||||
|
||||
@Autowired
|
||||
private ConsultationService consultationService;
|
||||
|
||||
@Autowired
|
||||
private MedicalRecordService medicalRecordService;
|
||||
|
||||
@Override
|
||||
public Payment createPayment(PaymentDTO paymentDTO) {
|
||||
Payment payment = new Payment();
|
||||
|
||||
if (paymentDTO.consultationId() != null) {
|
||||
payment.setConsultation(consultationService.findConsultationById(paymentDTO.consultationId()));
|
||||
}
|
||||
|
||||
if (paymentDTO.medicalRecordId() != null) {
|
||||
payment.setMedicalRecord(medicalRecordService.getMedicalRecordById(paymentDTO.medicalRecordId()));
|
||||
}
|
||||
|
||||
payment.setAmount(paymentDTO.amount());
|
||||
payment.setPaymentMethod(paymentDTO.paymentMethod());
|
||||
payment.setPaymentDate(paymentDTO.paymentDate());
|
||||
|
||||
return paymentRepository.save(payment);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Payment getPaymentById(Long id) {
|
||||
return paymentRepository.findById(id)
|
||||
.orElseThrow(() -> new EntityNotFoundException("Payment with ID " + id + " not found."));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<Payment> getAllPayments(Pageable pageable) {
|
||||
return paymentRepository.findAll(pageable);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,144 @@
|
||||
package com.mirna.hospitalmanagementapi.application.services;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.PrescriptionDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.inventory.InventoryTransactionDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.MedicalRecord;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.Prescription;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.inventory.InventoryItem;
|
||||
import com.mirna.hospitalmanagementapi.domain.enums.TransactionType;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.PrescriptionRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.MedicalRecordService;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.PrescriptionService;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.inventory.InventoryItemService;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.inventory.InventoryTransactionService;
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import com.mirna.hospitalmanagementapi.domain.exceptions.ConsultationValidationException;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
public class PrescriptionServiceImpl implements PrescriptionService {
|
||||
|
||||
@Autowired
|
||||
private PrescriptionRepository prescriptionRepository;
|
||||
|
||||
@Autowired
|
||||
private MedicalRecordService medicalRecordService;
|
||||
|
||||
@Autowired
|
||||
private InventoryItemService inventoryItemService;
|
||||
|
||||
@Autowired
|
||||
private InventoryTransactionService inventoryTransactionService;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Prescription createPrescription(PrescriptionDTO prescriptionDTO) throws EntityNotFoundException, ConsultationValidationException {
|
||||
MedicalRecord medicalRecord = medicalRecordService.getMedicalRecordById(prescriptionDTO.medicalRecordId());
|
||||
if (medicalRecord == null) {
|
||||
throw new EntityNotFoundException("Medical record with ID " + prescriptionDTO.medicalRecordId() + " not found.");
|
||||
}
|
||||
|
||||
InventoryItem inventoryItem = inventoryItemService.findInventoryItemEntityById(prescriptionDTO.inventoryItemId());
|
||||
if (inventoryItem == null) {
|
||||
throw new EntityNotFoundException("Inventory item with ID " + prescriptionDTO.inventoryItemId() + " not found.");
|
||||
}
|
||||
|
||||
if (inventoryItem.getCurrentStock() < prescriptionDTO.quantity()) {
|
||||
throw new ConsultationValidationException("Not enough stock for this medication. Available: " + inventoryItem.getCurrentStock());
|
||||
}
|
||||
|
||||
Prescription prescription = new Prescription(medicalRecord, inventoryItem, prescriptionDTO.quantity(), prescriptionDTO.instructions());
|
||||
Prescription savedPrescription = prescriptionRepository.save(prescription);
|
||||
|
||||
InventoryTransactionDTO transactionDTO = new InventoryTransactionDTO();
|
||||
transactionDTO.setItemId(inventoryItem.getId());
|
||||
transactionDTO.setTransactionType(TransactionType.OUT);
|
||||
transactionDTO.setQuantity(prescriptionDTO.quantity());
|
||||
transactionDTO.setRelatedDocumentId(savedPrescription.getId());
|
||||
transactionDTO.setNotes("เบิกยาตามใบสั่งยาเลขที่ " + savedPrescription.getId());
|
||||
transactionDTO.setTransactionDate(ZonedDateTime.now());
|
||||
|
||||
inventoryTransactionService.addTransaction(transactionDTO);
|
||||
|
||||
return savedPrescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Prescription getPrescriptionById(UUID id) throws EntityNotFoundException {
|
||||
return prescriptionRepository.findById(id)
|
||||
.orElseThrow(() -> new EntityNotFoundException("Prescription not found with ID: " + id));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Prescription updatePrescription(UUID id, PrescriptionDTO prescriptionDTO)
|
||||
throws EntityNotFoundException, ConsultationValidationException {
|
||||
|
||||
Prescription existingPrescription = getPrescriptionById(id);
|
||||
|
||||
// Get old item and quantity before any changes
|
||||
InventoryItem oldInventoryItem = existingPrescription.getInventoryItem();
|
||||
Integer oldQuantity = existingPrescription.getQuantity();
|
||||
|
||||
// Get the new item and quantity from the DTO
|
||||
InventoryItem newInventoryItem = inventoryItemService.findInventoryItemEntityById(prescriptionDTO.inventoryItemId());
|
||||
if (newInventoryItem == null) {
|
||||
throw new EntityNotFoundException("Inventory item with ID " + prescriptionDTO.inventoryItemId() + " not found.");
|
||||
}
|
||||
Integer newQuantity = prescriptionDTO.quantity();
|
||||
|
||||
// Determine the available stock for the new item.
|
||||
// If the item has changed, we only care about the new item's current stock.
|
||||
// If the item is the same, we must first "return" the old quantity to the stock count
|
||||
// before checking if the new quantity is available.
|
||||
Integer stockForCheck = newInventoryItem.getCurrentStock();
|
||||
if (oldInventoryItem.equals(newInventoryItem)) {
|
||||
stockForCheck = stockForCheck + oldQuantity;
|
||||
}
|
||||
|
||||
// Now, perform the stock validation check with the adjusted stock.
|
||||
if (stockForCheck < newQuantity) {
|
||||
throw new ConsultationValidationException("Not enough stock for this medication. Available: " + stockForCheck);
|
||||
}
|
||||
|
||||
// Create transaction to return old quantity
|
||||
InventoryTransactionDTO returnDto = new InventoryTransactionDTO();
|
||||
returnDto.setItemId(oldInventoryItem.getId());
|
||||
returnDto.setTransactionType(TransactionType.IN);
|
||||
returnDto.setQuantity(oldQuantity);
|
||||
returnDto.setRelatedDocumentId(existingPrescription.getId());
|
||||
returnDto.setNotes("คืนสต็อกจากการแก้ไขใบสั่งยาเลขที่ " + existingPrescription.getId());
|
||||
returnDto.setTransactionDate(ZonedDateTime.now());
|
||||
inventoryTransactionService.addTransaction(returnDto);
|
||||
|
||||
// Update the prescription entity with the new details
|
||||
existingPrescription.setMedicalRecord(medicalRecordService.getMedicalRecordById(prescriptionDTO.medicalRecordId()));
|
||||
existingPrescription.setInventoryItem(newInventoryItem);
|
||||
existingPrescription.setQuantity(newQuantity);
|
||||
existingPrescription.setInstructions(prescriptionDTO.instructions());
|
||||
|
||||
// Create transaction to withdraw new quantity
|
||||
InventoryTransactionDTO newDeductionDto = new InventoryTransactionDTO();
|
||||
newDeductionDto.setItemId(newInventoryItem.getId());
|
||||
newDeductionDto.setTransactionType(TransactionType.OUT);
|
||||
newDeductionDto.setQuantity(newQuantity);
|
||||
newDeductionDto.setRelatedDocumentId(existingPrescription.getId());
|
||||
newDeductionDto.setNotes("เบิกยาใหม่จากการแก้ไขใบสั่งยาเลขที่ " + existingPrescription.getId());
|
||||
newDeductionDto.setTransactionDate(ZonedDateTime.now());
|
||||
inventoryTransactionService.addTransaction(newDeductionDto);
|
||||
|
||||
return prescriptionRepository.save(existingPrescription);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOwner(UUID prescriptionId, Long patientId) {
|
||||
return prescriptionRepository.findById(prescriptionId)
|
||||
.map(prescription -> prescription.getMedicalRecord().getPatient().getId().equals(patientId))
|
||||
.orElse(false);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,93 @@
|
||||
package com.mirna.hospitalmanagementapi.application.services;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.FinancialReportDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.PaymentRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.InsuranceClaimRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.inventory.InventoryTransactionRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.ReportService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.inventory.InventoryItem;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.inventory.InventoryItemRepository;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.AppointmentReportDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.ConsultationRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.LowStockItemDTO;
|
||||
|
||||
@Service
|
||||
public class ReportServiceImpl implements ReportService {
|
||||
|
||||
@Autowired
|
||||
private PaymentRepository paymentRepository;
|
||||
|
||||
@Autowired
|
||||
private InsuranceClaimRepository insuranceClaimRepository;
|
||||
|
||||
@Autowired
|
||||
private InventoryTransactionRepository inventoryTransactionRepository;
|
||||
|
||||
@Autowired
|
||||
private InventoryItemRepository inventoryItemRepository;
|
||||
|
||||
@Autowired
|
||||
private ConsultationRepository consultationRepository;
|
||||
|
||||
@Override
|
||||
public List<FinancialReportDTO> getFinancialReport(LocalDate startDate, LocalDate endDate) {
|
||||
|
||||
List<FinancialReportDTO> reports = new ArrayList<>();
|
||||
ZoneOffset zoneOffset = ZoneOffset.UTC;
|
||||
|
||||
for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) {
|
||||
|
||||
LocalDateTime startOfDay = date.atStartOfDay();
|
||||
LocalDateTime endOfDay = date.plusDays(1).atStartOfDay().minusNanos(1);
|
||||
|
||||
// แปลง LocalDateTime เป็น OffsetDateTime สำหรับ PaymentRepository
|
||||
OffsetDateTime startOffsetDateTime = startOfDay.atZone(ZoneId.systemDefault()).toOffsetDateTime();
|
||||
OffsetDateTime endOffsetDateTime = endOfDay.atZone(ZoneId.systemDefault()).toOffsetDateTime();
|
||||
BigDecimal totalRevenue = paymentRepository.sumAmountByDateRange(startOffsetDateTime, endOffsetDateTime);
|
||||
|
||||
// ใช้ LocalDateTime สำหรับ InsuranceClaimRepository
|
||||
BigDecimal totalInsuranceClaims = insuranceClaimRepository.sumClaimAmountByDateRange(startOfDay, endOfDay);
|
||||
|
||||
// แปลง LocalDateTime เป็น ZonedDateTime สำหรับ InventoryTransactionRepository
|
||||
ZonedDateTime startZoned = startOfDay.atZone(ZoneId.systemDefault());
|
||||
ZonedDateTime endZoned = endOfDay.atZone(ZoneId.systemDefault());
|
||||
BigDecimal totalInventoryCost = inventoryTransactionRepository.sumTotalCostByDateRange(startZoned, endZoned);
|
||||
|
||||
if (totalRevenue == null) totalRevenue = BigDecimal.ZERO;
|
||||
if (totalInsuranceClaims == null) totalInsuranceClaims = BigDecimal.ZERO;
|
||||
if (totalInventoryCost == null) totalInventoryCost = BigDecimal.ZERO;
|
||||
|
||||
reports.add(new FinancialReportDTO(date, totalRevenue, totalInsuranceClaims, totalInventoryCost));
|
||||
}
|
||||
|
||||
return reports;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<LowStockItemDTO> getLowStockItems(Pageable pageable) {
|
||||
return inventoryItemRepository.findItemsRunningLow(pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AppointmentReportDTO getAppointmentReport(LocalDate startDate, LocalDate endDate) {
|
||||
// ใช้ Timezone ที่ต้องการ เช่น Asia/Bangkok
|
||||
ZoneOffset zoneOffset = ZoneOffset.UTC;
|
||||
|
||||
OffsetDateTime startDateTime = startDate.atStartOfDay().atOffset(zoneOffset);
|
||||
OffsetDateTime endDateTime = endDate.atTime(LocalTime.MAX).atOffset(zoneOffset);
|
||||
|
||||
Long totalAppointments = consultationRepository.countAllByDateRange(startDateTime, endDateTime);
|
||||
Long canceledAppointments = consultationRepository.countCanceledByDateRange(startDateTime, endDateTime);
|
||||
Long uniquePatients = consultationRepository.countTotalPatientsByDateRange(startDateTime, endDateTime);
|
||||
|
||||
return new AppointmentReportDTO(totalAppointments, canceledAppointments, uniquePatients);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
package com.mirna.hospitalmanagementapi.application.services;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.Staff;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.StaffRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.StaffService;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.auth.User;
|
||||
import com.mirna.hospitalmanagementapi.domain.enums.Role;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.auth.UserRepository;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* This class is an implementation of the StaffService interface.
|
||||
*
|
||||
* This class provides methods to perform operations on Staff entity.
|
||||
*
|
||||
* @author FlookSP
|
||||
* @version 1.0
|
||||
*/
|
||||
@Service
|
||||
public class StaffServiceImpl implements StaffService {
|
||||
|
||||
@Autowired
|
||||
private StaffRepository staffRepository;
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Staff addStaff(Staff staff) {
|
||||
//เข้ารหัส password
|
||||
String encryptedPassword = passwordEncoder.encode(staff.getUser().getPassword());
|
||||
User user = new User(staff.getUser().getLogin(), encryptedPassword, Role.valueOf(staff.getUser().getRole().name()));
|
||||
|
||||
// บันทึกบัญชีผู้ใช้งานลงในฐานข้อมูล
|
||||
User savedUser = userRepository.save(user);
|
||||
|
||||
// ตั้งค่า User Entity ที่บันทึกแล้วให้กับ Staff Entity
|
||||
staff.setUser(savedUser);
|
||||
|
||||
// บันทึก Staff Entity ลงในฐานข้อมูล
|
||||
return staffRepository.save(staff);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package com.mirna.hospitalmanagementapi.application.services;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.inventory.SupplierDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.inventory.InventorySupplier;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.inventory.InventorySupplierRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.inventory.SupplierService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class SupplierServiceImpl implements SupplierService {
|
||||
|
||||
@Autowired
|
||||
private InventorySupplierRepository inventorySupplierRepository;
|
||||
|
||||
@Override
|
||||
public InventorySupplier addSupplier(SupplierDTO supplierDTO) {
|
||||
InventorySupplier newSupplier = new InventorySupplier(supplierDTO);
|
||||
return inventorySupplierRepository.save(newSupplier);
|
||||
}
|
||||
}
|
||||
@ -2,55 +2,103 @@ package com.mirna.hospitalmanagementapi.application.services;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.application.usecase.user.FindUserByLoginUseCase;
|
||||
import com.mirna.hospitalmanagementapi.application.usecase.user.SaveUserUseCase;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.auth.UserDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.auth.User;
|
||||
import com.mirna.hospitalmanagementapi.domain.enums.Role;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.UserService;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.auth.UserRepository;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.auth.UserUpdateUsernameDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.auth.UserUpdatePasswordDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.auth.UserUpdateRoleDTO;
|
||||
|
||||
/**
|
||||
* This class is an implementation of the UserService interface.
|
||||
*
|
||||
* This class provides methods to perform operations on User entity
|
||||
*
|
||||
* @author Mirna Gama
|
||||
* @version 1.0
|
||||
* @author Mirna Gama (Extended by FlookSP)
|
||||
* @version 1.1
|
||||
*/
|
||||
|
||||
@Service
|
||||
public class UserServiceImpl implements UserService {
|
||||
|
||||
@Autowired
|
||||
private SaveUserUseCase saveUser;
|
||||
@Autowired
|
||||
private SaveUserUseCase saveUser;
|
||||
|
||||
@Autowired
|
||||
private FindUserByLoginUseCase findUserByLogin;
|
||||
@Autowired
|
||||
private FindUserByLoginUseCase findUserByLogin;
|
||||
|
||||
/**
|
||||
* Finds a stored user information by login.
|
||||
*
|
||||
* @param login A string representing the user's system login
|
||||
* @return The corresponding user information if successful, or null if it is non-existent.
|
||||
*/
|
||||
@Override
|
||||
public UserDetails findUserByLogin(String login) {
|
||||
return findUserByLogin.execute(login);
|
||||
}
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
/**
|
||||
* Adds a new user to the repository.
|
||||
*
|
||||
* @param userDTO A data transfer object representing a user to add.
|
||||
* @return The saved user if successful, or null if there is an error.
|
||||
*/
|
||||
@Override
|
||||
public User addUser(UserDTO userDTO) {
|
||||
@Autowired
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
User user = new User(userDTO);
|
||||
@Override
|
||||
public UserDetails findUserByLogin(String login) {
|
||||
return findUserByLogin.execute(login);
|
||||
}
|
||||
|
||||
return saveUser.execute(user);
|
||||
}
|
||||
@Override
|
||||
public User addUser(User user) {
|
||||
return saveUser.execute(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public User updateUsername(Long id, UserUpdateUsernameDTO userUpdateUsernameDTO) {
|
||||
User user = findUserById(id);
|
||||
user.setLogin(userUpdateUsernameDTO.username());
|
||||
return userRepository.save(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public User updatePassword(Long id, UserUpdatePasswordDTO userUpdatePasswordDTO) {
|
||||
User user = findUserById(id);
|
||||
user.setPassword(passwordEncoder.encode(userUpdatePasswordDTO.password()));
|
||||
return userRepository.save(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public User updateRole(Long id, UserUpdateRoleDTO userUpdateRoleDTO) {
|
||||
User user = findUserById(id);
|
||||
try {
|
||||
Role newRole = Role.valueOf(userUpdateRoleDTO.role().toUpperCase());
|
||||
user.setRole(newRole);
|
||||
return userRepository.save(user);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException("Invalid role provided: " + userUpdateRoleDTO.role());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public User deactivateUser(Long id) {
|
||||
User user = findUserById(id);
|
||||
user.setEnabled(false);
|
||||
return userRepository.save(user);
|
||||
}
|
||||
|
||||
private User findUserById(Long id) {
|
||||
return userRepository.findById(id)
|
||||
.orElseThrow(() -> new UsernameNotFoundException("User not found with id: " + id));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public User activateUser(Long id) {
|
||||
User user = findUserById(id);
|
||||
user.setEnabled(true);
|
||||
return userRepository.save(user);
|
||||
}
|
||||
}
|
||||
@ -6,11 +6,29 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticatio
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.auth.UserDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.auth.User;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.UserService;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.auth.AuthService;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.auth.PatientRegistrationDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.auth.DoctorRegistrationDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.enums.Role;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.Patient;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.Doctor;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.PatientRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.DoctorRepository;
|
||||
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
import jakarta.persistence.PersistenceException;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.auth.StaffRegistrationDTO;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.Staff;
|
||||
import com.mirna.hospitalmanagementapi.domain.services.StaffService;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.Nurse;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.NurseRepository;
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.auth.NurseRegistrationDTO;
|
||||
|
||||
/**
|
||||
* This class is an implementation of the AuthService interface.
|
||||
@ -23,42 +41,142 @@ import com.mirna.hospitalmanagementapi.domain.services.auth.AuthService;
|
||||
@Service
|
||||
public class AuthServiceImpl implements AuthService {
|
||||
|
||||
@Autowired
|
||||
private AuthenticationManager manager;
|
||||
@Autowired
|
||||
private AuthenticationManager manager;
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@Autowired
|
||||
private PasswordEncoder passwordEncoder;
|
||||
@Autowired
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
/**
|
||||
* Performs the user login
|
||||
*
|
||||
* @param userDTO Data transfer object containing user credentials for authentication operations
|
||||
* @return A fully authentication object including the credentials
|
||||
*/
|
||||
@Override
|
||||
public Authentication login(UserDTO userDTO) {
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(userDTO.login(),
|
||||
userDTO.password());
|
||||
@Autowired
|
||||
private PatientRepository patientRepository;
|
||||
|
||||
return manager.authenticate(token);
|
||||
}
|
||||
@Autowired
|
||||
private DoctorRepository doctorRepository;
|
||||
|
||||
/**
|
||||
* Performs the user registration
|
||||
*
|
||||
* @param userDTO Data transfer object containing user credentials for authentication operations
|
||||
* @return A user object including the credentials
|
||||
*/
|
||||
@Override
|
||||
public User register(UserDTO userDTO) {
|
||||
@Autowired
|
||||
private StaffService staffService;
|
||||
|
||||
String encodedPassword = passwordEncoder.encode(userDTO.password());
|
||||
userDTO = new UserDTO(userDTO.login(), encodedPassword);
|
||||
@Autowired
|
||||
private NurseRepository nurseRepository;
|
||||
|
||||
return this.userService.addUser(userDTO);
|
||||
}
|
||||
/**
|
||||
* Performs the user login
|
||||
* * @param userDTO Data transfer object containing user credentials for authentication operations
|
||||
* @return A fully authentication object including the credentials
|
||||
*/
|
||||
@Override
|
||||
public Authentication login(UserDTO userDTO) {
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(userDTO.login(),
|
||||
userDTO.password());
|
||||
|
||||
return manager.authenticate(token);
|
||||
}
|
||||
/*
|
||||
@Override
|
||||
public User register(UserDTO userDTO) {
|
||||
String encodedPassword = passwordEncoder.encode(userDTO.password());
|
||||
// แก้ไขจาก userDTO เป็น User entity
|
||||
User user = new User(userDTO.login(), encodedPassword, null); // ต้องกำหนด role ด้วย
|
||||
return this.userService.addUser(user);
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Performs the user registration (patients)
|
||||
* * @param registrationDTO Data transfer object containing user and patient creation
|
||||
* @return A user object including the credentials
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public User registerPatient(PatientRegistrationDTO registrationDTO) {
|
||||
// 1. สร้างและบันทึก User
|
||||
User user = new User();
|
||||
user.setLogin(registrationDTO.login());
|
||||
user.setPassword(passwordEncoder.encode(registrationDTO.password()));
|
||||
user.setRole(Role.ROLE_PATIENT);
|
||||
User savedUser = this.userService.addUser(user);
|
||||
|
||||
// 2. สร้างโปรไฟล์ผู้ป่วยและเชื่อมโยงกับ User
|
||||
Patient patient = new Patient(registrationDTO.patientData(), savedUser);
|
||||
this.patientRepository.save(patient);
|
||||
|
||||
return savedUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new user account for a doctor and links it to an existing doctor record.
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public User registerDoctor(DoctorRegistrationDTO registrationDTO) {
|
||||
// 1. ตรวจสอบว่ามีข้อมูลแพทย์ตาม CRM ที่ให้มาหรือไม่
|
||||
Doctor doctor = doctorRepository.findByCrm(registrationDTO.getCrm());
|
||||
if (doctor == null) {
|
||||
throw new EntityNotFoundException("ไม่พบข้อมูลแพทย์ที่มี CRM: " + registrationDTO.getCrm());
|
||||
}
|
||||
|
||||
// 2. ตรวจสอบว่าแพทย์คนนี้มีบัญชีผู้ใช้แล้วหรือยัง
|
||||
if (doctor.getUser() != null) {
|
||||
throw new PersistenceException("แพทย์คนนี้มีบัญชีผู้ใช้งานในระบบแล้ว.");
|
||||
}
|
||||
|
||||
// 3. สร้าง User ใหม่สำหรับแพทย์
|
||||
User user = new User();
|
||||
user.setLogin(registrationDTO.getLogin());
|
||||
user.setPassword(passwordEncoder.encode(registrationDTO.getPassword()));
|
||||
user.setRole(Role.ROLE_DOCTOR);
|
||||
user.setEnabled(true);
|
||||
User savedUser = this.userService.addUser(user);
|
||||
|
||||
// 4. เชื่อมโยงบัญชี User กับข้อมูลแพทย์
|
||||
doctor.setUser(savedUser);
|
||||
doctorRepository.save(doctor);
|
||||
|
||||
return savedUser;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Staff registerStaff(StaffRegistrationDTO dto) {
|
||||
// สร้าง User Entity จากข้อมูล DTO
|
||||
User user = new User(dto.login(), passwordEncoder.encode(dto.password()), dto.role());
|
||||
|
||||
// สร้าง Staff Entity จากข้อมูล DTO และ User Entity ที่สร้างไว้
|
||||
Staff staff = new Staff(dto.name(), dto.email(), dto.telephone(), user);
|
||||
|
||||
// บันทึก Staff Entity โดย StaffService
|
||||
return staffService.addStaff(staff);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new user account for a nurse and links it to an existing nurse record.
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public User registerNurseAndLink(NurseRegistrationDTO registrationDTO) {
|
||||
// 1. ตรวจสอบว่ามีข้อมูลพยาบาลตาม licenseNumber ที่ให้มาหรือไม่
|
||||
Nurse nurse = nurseRepository.findByLicenseNumber(registrationDTO.licenseNumber())
|
||||
.orElseThrow(() -> new EntityNotFoundException("ไม่พบข้อมูลพยาบาลที่มีหมายเลขใบอนุญาต: " + registrationDTO.licenseNumber()));
|
||||
|
||||
// 2. ตรวจสอบว่าพยาบาลคนนี้มีบัญชีผู้ใช้แล้วหรือยัง
|
||||
if (nurse.getUser() != null) {
|
||||
throw new PersistenceException("พยาบาลคนนี้มีบัญชีผู้ใช้งานในระบบแล้ว.");
|
||||
}
|
||||
|
||||
// 3. สร้าง User ใหม่สำหรับพยาบาล
|
||||
User user = new User();
|
||||
user.setLogin(registrationDTO.login());
|
||||
user.setPassword(passwordEncoder.encode(registrationDTO.password()));
|
||||
user.setRole(Role.ROLE_NURSE);
|
||||
user.setEnabled(true);
|
||||
User savedUser = this.userService.addUser(user);
|
||||
|
||||
// 4. เชื่อมโยงบัญชี User กับข้อมูลพยาบาล
|
||||
nurse.setUser(savedUser);
|
||||
nurseRepository.save(nurse);
|
||||
|
||||
return savedUser;
|
||||
}
|
||||
}
|
||||
@ -11,38 +11,24 @@ import com.auth0.jwt.JWT;
|
||||
import com.auth0.jwt.algorithms.Algorithm;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.auth.User;
|
||||
|
||||
/**
|
||||
* This class is used to execute the JWT create method using Algorithm HMAC256 along with the authenticated user login and id
|
||||
*
|
||||
* @author Mirna Gama
|
||||
* @version 1.0
|
||||
*/
|
||||
@Component
|
||||
public class CreateJWTUseCase {
|
||||
|
||||
@Value("${api.security.token.secret}")
|
||||
@Value("${api.security.token.secret}")
|
||||
private String secret;
|
||||
|
||||
/** Creates a json web token
|
||||
*
|
||||
* @param user The authenticated user
|
||||
* @return A string containing the json web token signed with Algorithm HMAC256
|
||||
*/
|
||||
public String execute(User user) {
|
||||
Algorithm algorithm = Algorithm.HMAC256(secret);
|
||||
public String execute(User user) {
|
||||
Algorithm algorithm = Algorithm.HMAC256(secret);
|
||||
|
||||
return JWT.create().withIssuer("Hospital-Management-API")
|
||||
.withSubject(user.getLogin())
|
||||
.withClaim("id", user.getId())
|
||||
.withExpiresAt(_getExpirationDate())
|
||||
.sign(algorithm);
|
||||
}
|
||||
return JWT.create().withIssuer("Hospital-Management-API (Extended Version)")
|
||||
.withSubject(user.getLogin())
|
||||
.withClaim("id", user.getId())
|
||||
.withClaim("roles", user.getRole().name()) // <-- เพิ่มบรรทัดนี้
|
||||
.withExpiresAt(_getExpirationDate())
|
||||
.sign(algorithm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an expiration date for the token based on 2 hours duration
|
||||
* @return Instant object containing the expiration date
|
||||
*/
|
||||
private Instant _getExpirationDate() {
|
||||
return LocalDateTime.now().plusHours(2).toInstant(ZoneOffset.of("-03:00"));
|
||||
}
|
||||
private Instant _getExpirationDate() {
|
||||
return LocalDateTime.now().plusHours(2).toInstant(ZoneOffset.of("-03:00"));
|
||||
}
|
||||
}
|
||||
@ -29,7 +29,7 @@ public class GetJWTSubjectUseCase {
|
||||
public String execute(String token) {
|
||||
Algorithm algorithm = Algorithm.HMAC256(secret);
|
||||
DecodedJWT decodedJWT = JWT.require(algorithm)
|
||||
.withIssuer("Hospital-Management-API")
|
||||
.withIssuer("Hospital-Management-API (Extended Version)")
|
||||
.build()
|
||||
.verify(token);
|
||||
|
||||
|
||||
@ -1,34 +1,22 @@
|
||||
package com.mirna.hospitalmanagementapi.application.usecase.consultation;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.Consultation;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.ConsultationRepository;
|
||||
|
||||
/**
|
||||
* This class is used to execute the findConsultationByDoctorAndDate method from consultation repository
|
||||
*
|
||||
* @author Mirna Gama
|
||||
* @version 1.0
|
||||
*/
|
||||
@Component
|
||||
public class FindConsultationByDoctorAndDateUseCase {
|
||||
|
||||
@Autowired
|
||||
private ConsultationRepository consultationRepository;
|
||||
@Autowired
|
||||
private ConsultationRepository consultationRepository;
|
||||
|
||||
/**
|
||||
* Executes the findConsultationByDoctorAndDate method from Consultation repository
|
||||
*
|
||||
* @param doctorId The doctor's id from the consultation
|
||||
* @param consultationDate The date of the consultation
|
||||
* @return The corresponding consultation if successful, or null if it is non-existent
|
||||
*
|
||||
*/
|
||||
public Consultation execute(Long doctorId, LocalDateTime consultationDate) {
|
||||
return this.consultationRepository.findConsultationByDoctorAndDate(doctorId, consultationDate);
|
||||
}
|
||||
public Consultation execute(Long doctorId, OffsetDateTime consultationDate) {
|
||||
// เพิ่มบรรทัดนี้เพื่อกำหนดจุดสิ้นสุดของช่วงเวลา
|
||||
OffsetDateTime consultationDatePlusOneMinute = consultationDate.plusMinutes(1);
|
||||
|
||||
return this.consultationRepository.findConsultationByDoctorAndDate(doctorId, consultationDate, consultationDatePlusOneMinute);
|
||||
}
|
||||
}
|
||||
@ -1,34 +1,22 @@
|
||||
package com.mirna.hospitalmanagementapi.application.usecase.consultation;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.Consultation;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.ConsultationRepository;
|
||||
|
||||
/**
|
||||
* This class is used to execute the findConsultationByPatientAndDate method from consultation repository
|
||||
*
|
||||
* @author Mirna Gama
|
||||
* @version 1.0
|
||||
*/
|
||||
@Component
|
||||
public class FindConsultationByPatientAndDateUseCase {
|
||||
|
||||
@Autowired
|
||||
private ConsultationRepository consultationRepository;
|
||||
@Autowired
|
||||
private ConsultationRepository consultationRepository;
|
||||
|
||||
/**
|
||||
* Executes the findConsultationByPatientAndDate method from Consultation repository
|
||||
*
|
||||
* @param patientId The patient's id from the consultation
|
||||
* @param consultationDate The date of the consultation
|
||||
* @return The corresponding consultation if successful, or null if it is non-existent
|
||||
*
|
||||
*/
|
||||
public Consultation execute(Long patientId, LocalDateTime consultationDate) {
|
||||
return this.consultationRepository.findConsultationByPatientAndDate(patientId, consultationDate);
|
||||
}
|
||||
public Consultation execute(Long patientId, OffsetDateTime consultationDate) {
|
||||
// เพิ่มบรรทัดนี้เพื่อกำหนดจุดสิ้นสุดของช่วงเวลา
|
||||
OffsetDateTime consultationDatePlusOneMinute = consultationDate.plusMinutes(1);
|
||||
|
||||
return this.consultationRepository.findConsultationByPatientAndDate(patientId, consultationDate, consultationDatePlusOneMinute);
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,9 @@
|
||||
// ไฟล์: FindOneFreeDoctorBySpecialtyUseCase.java
|
||||
package com.mirna.hospitalmanagementapi.application.usecase.doctor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -9,27 +12,21 @@ import com.mirna.hospitalmanagementapi.domain.entities.Doctor;
|
||||
import com.mirna.hospitalmanagementapi.domain.enums.Specialty;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.DoctorRepository;
|
||||
|
||||
/**
|
||||
* This class is used to execute the findOneFreeDoctorBySpecialty method
|
||||
*
|
||||
* @author Mirna Gama
|
||||
* @version 1.0
|
||||
*/
|
||||
@Component
|
||||
public class FindOneFreeDoctorBySpecialtyUseCase {
|
||||
|
||||
@Autowired
|
||||
private DoctorRepository doctorRepository;
|
||||
@Autowired
|
||||
private DoctorRepository doctorRepository;
|
||||
|
||||
/**
|
||||
* Executes the findOneFreeDoctorBySpecialty method from Doctor repository
|
||||
*
|
||||
* @param specialty Desired specialty for doctor search
|
||||
* @param consultationDate Date to check if the doctor is free
|
||||
* @return A random free doctor with the defined specialty if successful, or null if it is non-existent
|
||||
*
|
||||
*/
|
||||
public Doctor execute(Specialty specialty, LocalDateTime consultationDate) {
|
||||
return doctorRepository.findOneFreeDoctorBySpecialty(specialty, consultationDate);
|
||||
}
|
||||
public Doctor execute(Specialty specialty, OffsetDateTime consultationDate) {
|
||||
// ใช้ Query ใหม่ที่แม่นยำกว่าเดิม
|
||||
List<Doctor> freeDoctors = doctorRepository.findFreeDoctorsBySpecialty(specialty, consultationDate);
|
||||
|
||||
if (freeDoctors.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// เลือกแพทย์แบบสุ่มจากรายการที่ว่าง
|
||||
return freeDoctors.get(new Random().nextInt(freeDoctors.size()));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package com.mirna.hospitalmanagementapi.application.usecase.inventory;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.inventory.InventoryItem;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.inventory.InventoryItemRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import java.util.UUID;
|
||||
|
||||
@Component
|
||||
public class FindInventoryItemByIdUseCase {
|
||||
|
||||
@Autowired
|
||||
private InventoryItemRepository inventoryItemRepository;
|
||||
|
||||
public InventoryItem execute(UUID id) {
|
||||
return inventoryItemRepository.findById(id).orElse(null);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package com.mirna.hospitalmanagementapi.application.usecase.inventory;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.inventory.InventoryItem;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.inventory.InventoryItemRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class SaveInventoryItemUseCase {
|
||||
|
||||
@Autowired
|
||||
private InventoryItemRepository inventoryItemRepository;
|
||||
|
||||
public InventoryItem execute(InventoryItem item) {
|
||||
return inventoryItemRepository.save(item);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package com.mirna.hospitalmanagementapi.application.usecase.medicalrecord;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.MedicalRecord;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.MedicalRecordRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class FindMedicalRecordByIdUseCase {
|
||||
|
||||
@Autowired
|
||||
private MedicalRecordRepository medicalRecordRepository;
|
||||
|
||||
public MedicalRecord execute(Long id) {
|
||||
return medicalRecordRepository.findById(id).orElse(null);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package com.mirna.hospitalmanagementapi.application.usecase.medicalrecord;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.MedicalRecord;
|
||||
import com.mirna.hospitalmanagementapi.domain.repositories.MedicalRecordRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class SaveMedicalRecordUseCase {
|
||||
|
||||
@Autowired
|
||||
private MedicalRecordRepository medicalRecordRepository;
|
||||
|
||||
public MedicalRecord execute(MedicalRecord medicalRecord) {
|
||||
return medicalRecordRepository.save(medicalRecord);
|
||||
}
|
||||
}
|
||||
@ -18,7 +18,7 @@ public record AddressDTO(
|
||||
String neighborhood,
|
||||
|
||||
@NotBlank(message="zipCode cannot be blank")
|
||||
@Pattern(regexp="\\d{8}", message="invalid format for zipCode")
|
||||
@Pattern(regexp="\\d{5}", message="invalid format for zipCode")
|
||||
String zipCode,
|
||||
|
||||
@NotBlank(message="city cannot be blank")
|
||||
|
||||
@ -0,0 +1,7 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos;
|
||||
|
||||
public record AppointmentReportDTO(
|
||||
Long totalAppointments,
|
||||
Long canceledAppointments,
|
||||
Long totalPatients
|
||||
) {}
|
||||
@ -0,0 +1,41 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
public class BillableItemDTO {
|
||||
|
||||
@NotNull(message = "Item description is required")
|
||||
private String itemDescription;
|
||||
|
||||
@NotNull(message = "Quantity is required")
|
||||
private Integer quantity;
|
||||
|
||||
@NotNull(message = "Unit price is required")
|
||||
private BigDecimal unitPrice;
|
||||
|
||||
// Getters and Setters
|
||||
public String getItemDescription() {
|
||||
return itemDescription;
|
||||
}
|
||||
|
||||
public void setItemDescription(String itemDescription) {
|
||||
this.itemDescription = itemDescription;
|
||||
}
|
||||
|
||||
public Integer getQuantity() {
|
||||
return quantity;
|
||||
}
|
||||
|
||||
public void setQuantity(Integer quantity) {
|
||||
this.quantity = quantity;
|
||||
}
|
||||
|
||||
public BigDecimal getUnitPrice() {
|
||||
return unitPrice;
|
||||
}
|
||||
|
||||
public void setUnitPrice(BigDecimal unitPrice) {
|
||||
this.unitPrice = unitPrice;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos;
|
||||
|
||||
import java.util.List;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
public class BillingDTO {
|
||||
|
||||
@NotNull(message = "Medical Record ID is required")
|
||||
private Long medicalRecordId;
|
||||
|
||||
private List<BillableItemDTO> billableItems;
|
||||
|
||||
// Getters and Setters
|
||||
public Long getMedicalRecordId() {
|
||||
return medicalRecordId;
|
||||
}
|
||||
|
||||
public void setMedicalRecordId(Long medicalRecordId) {
|
||||
this.medicalRecordId = medicalRecordId;
|
||||
}
|
||||
|
||||
public List<BillableItemDTO> getBillableItems() {
|
||||
return billableItems;
|
||||
}
|
||||
|
||||
public void setBillableItems(List<BillableItemDTO> billableItems) {
|
||||
this.billableItems = billableItems;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.time.LocalTime;
|
||||
import java.time.DayOfWeek;
|
||||
|
||||
/**
|
||||
* A data transfer object representing a doctor schedule
|
||||
*
|
||||
* @author FlookSP
|
||||
* @version 1.0
|
||||
*/
|
||||
public record DoctorScheduleDTO(
|
||||
|
||||
@NotNull(message = "Doctor ID cannot be null")
|
||||
Long doctorId,
|
||||
|
||||
@NotNull(message = "Day of week cannot be null")
|
||||
DayOfWeek dayOfWeek,
|
||||
|
||||
@NotNull(message = "Start time cannot be null")
|
||||
LocalTime startTime,
|
||||
|
||||
@NotNull(message = "End time cannot be null")
|
||||
LocalTime endTime
|
||||
) {}
|
||||
@ -0,0 +1,37 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
|
||||
public class FinancialReportDTO {
|
||||
|
||||
private LocalDate date;
|
||||
private BigDecimal totalRevenue;
|
||||
private BigDecimal totalInsuranceClaims;
|
||||
private BigDecimal totalInventoryCost;
|
||||
|
||||
// Constructors
|
||||
public FinancialReportDTO(LocalDate date, BigDecimal totalRevenue, BigDecimal totalInsuranceClaims, BigDecimal totalInventoryCost) {
|
||||
this.date = date;
|
||||
this.totalRevenue = totalRevenue;
|
||||
this.totalInsuranceClaims = totalInsuranceClaims;
|
||||
this.totalInventoryCost = totalInventoryCost;
|
||||
}
|
||||
|
||||
// Getters
|
||||
public LocalDate getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public BigDecimal getTotalRevenue() {
|
||||
return totalRevenue;
|
||||
}
|
||||
|
||||
public BigDecimal getTotalInsuranceClaims() {
|
||||
return totalInsuranceClaims;
|
||||
}
|
||||
|
||||
public BigDecimal getTotalInventoryCost() {
|
||||
return totalInventoryCost;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,74 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
public class InsuranceClaimDTO {
|
||||
|
||||
@NotNull(message = "Billing ID is required")
|
||||
private Long billingId;
|
||||
|
||||
@NotNull(message = "Insurance Provider ID is required")
|
||||
private Long insuranceProviderId;
|
||||
|
||||
@NotBlank(message = "Claim number is required")
|
||||
private String claimNumber;
|
||||
|
||||
@NotNull(message = "Submission date is required")
|
||||
private LocalDateTime submissionDate;
|
||||
|
||||
private BigDecimal approvedAmount;
|
||||
|
||||
private String claimStatus; // Can be an Enum in the future
|
||||
|
||||
// Getters and Setters
|
||||
public Long getBillingId() {
|
||||
return billingId;
|
||||
}
|
||||
|
||||
public void setBillingId(Long billingId) {
|
||||
this.billingId = billingId;
|
||||
}
|
||||
|
||||
public Long getInsuranceProviderId() {
|
||||
return insuranceProviderId;
|
||||
}
|
||||
|
||||
public void setInsuranceProviderId(Long insuranceProviderId) {
|
||||
this.insuranceProviderId = insuranceProviderId;
|
||||
}
|
||||
|
||||
public String getClaimNumber() {
|
||||
return claimNumber;
|
||||
}
|
||||
|
||||
public void setClaimNumber(String claimNumber) {
|
||||
this.claimNumber = claimNumber;
|
||||
}
|
||||
|
||||
public LocalDateTime getSubmissionDate() {
|
||||
return submissionDate;
|
||||
}
|
||||
|
||||
public void setSubmissionDate(LocalDateTime submissionDate) {
|
||||
this.submissionDate = submissionDate;
|
||||
}
|
||||
|
||||
public BigDecimal getApprovedAmount() {
|
||||
return approvedAmount;
|
||||
}
|
||||
|
||||
public void setApprovedAmount(BigDecimal approvedAmount) {
|
||||
this.approvedAmount = approvedAmount;
|
||||
}
|
||||
|
||||
public String getClaimStatus() {
|
||||
return claimStatus;
|
||||
}
|
||||
|
||||
public void setClaimStatus(String claimStatus) {
|
||||
this.claimStatus = claimStatus;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
public record InsuranceProviderDTO(
|
||||
@NotBlank(message = "Provider name is required")
|
||||
@Size(min = 3, max = 255, message = "Provider name must be between 3 and 255 characters")
|
||||
String providerName,
|
||||
|
||||
String contactPerson,
|
||||
|
||||
String contactEmail,
|
||||
|
||||
String phoneNumber
|
||||
) {}
|
||||
@ -0,0 +1,80 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.enums.LabTestStatus;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* DTO สำหรับการส่งผ่านข้อมูลผลการตรวจแล็บ
|
||||
*
|
||||
* @author FlookSP
|
||||
* @version 1.0
|
||||
*/
|
||||
public class LabResultDTO {
|
||||
|
||||
private UUID id;
|
||||
|
||||
@NotBlank(message = "ชื่อการทดสอบต้องไม่ว่างเปล่า")
|
||||
private String testName;
|
||||
|
||||
private Double resultValue;
|
||||
|
||||
private String unit;
|
||||
|
||||
private String referenceRange;
|
||||
|
||||
@NotNull(message = "สถานะการตรวจต้องไม่เป็นค่าว่าง")
|
||||
private LabTestStatus status;
|
||||
|
||||
public LabResultDTO() {
|
||||
}
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTestName() {
|
||||
return testName;
|
||||
}
|
||||
|
||||
public void setTestName(String testName) {
|
||||
this.testName = testName;
|
||||
}
|
||||
|
||||
public Double getResultValue() {
|
||||
return resultValue;
|
||||
}
|
||||
|
||||
public void setResultValue(Double resultValue) {
|
||||
this.resultValue = resultValue;
|
||||
}
|
||||
|
||||
public String getUnit() {
|
||||
return unit;
|
||||
}
|
||||
|
||||
public void setUnit(String unit) {
|
||||
this.unit = unit;
|
||||
}
|
||||
|
||||
public String getReferenceRange() {
|
||||
return referenceRange;
|
||||
}
|
||||
|
||||
public void setReferenceRange(String referenceRange) {
|
||||
this.referenceRange = referenceRange;
|
||||
}
|
||||
|
||||
public LabTestStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(LabTestStatus status) {
|
||||
this.status = status;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.UUID;
|
||||
|
||||
public record LowStockItemDTO(
|
||||
UUID id,
|
||||
String itemName,
|
||||
Integer currentStock,
|
||||
String itemTypeName,
|
||||
BigDecimal unitPrice,
|
||||
Integer reorderLevel
|
||||
) {}
|
||||
@ -0,0 +1,14 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID; // เพิ่ม import
|
||||
|
||||
public record MedicalEquipmentScheduleDTO(
|
||||
@NotNull(message = "Medical equipment ID is required")
|
||||
UUID equipmentId,
|
||||
@NotNull(message = "Start time is required")
|
||||
LocalDateTime startTime,
|
||||
@NotNull(message = "End time is required")
|
||||
LocalDateTime endTime
|
||||
) {}
|
||||
@ -0,0 +1,30 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.MedicalEquipmentSchedule;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
public class MedicalEquipmentScheduleResponseDTO {
|
||||
|
||||
private Long id;
|
||||
private UUID equipmentId;
|
||||
private String equipmentName; // สามารถเพิ่มชื่ออุปกรณ์ได้
|
||||
private LocalDateTime startTime;
|
||||
private LocalDateTime endTime;
|
||||
|
||||
public MedicalEquipmentScheduleResponseDTO(MedicalEquipmentSchedule entity) {
|
||||
this.id = entity.getId();
|
||||
// เนื่องจากใน Service เราโหลด InventoryItem มาแล้ว จึงสามารถเข้าถึงได้
|
||||
this.equipmentId = entity.getInventoryItem().getId();
|
||||
this.equipmentName = entity.getInventoryItem().getItemName();
|
||||
this.startTime = entity.getStartTime();
|
||||
this.endTime = entity.getEndTime();
|
||||
}
|
||||
|
||||
// Getters
|
||||
public Long getId() { return id; }
|
||||
public UUID getEquipmentId() { return equipmentId; }
|
||||
public String getEquipmentName() { return equipmentName; }
|
||||
public LocalDateTime getStartTime() { return startTime; }
|
||||
public LocalDateTime getEndTime() { return endTime; }
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos;
|
||||
|
||||
public class MedicalRecordDTO {
|
||||
private Long patientId;
|
||||
private Long doctorId;
|
||||
private Long consultationId;
|
||||
private String diagnosis;
|
||||
private String treatment;
|
||||
private String notes;
|
||||
|
||||
// Getters and Setters
|
||||
public Long getPatientId() {
|
||||
return patientId;
|
||||
}
|
||||
public void setPatientId(Long patientId) {
|
||||
this.patientId = patientId;
|
||||
}
|
||||
public Long getDoctorId() {
|
||||
return doctorId;
|
||||
}
|
||||
public void setDoctorId(Long doctorId) {
|
||||
this.doctorId = doctorId;
|
||||
}
|
||||
public Long getConsultationId() {
|
||||
return consultationId;
|
||||
}
|
||||
public void setConsultationId(Long consultationId) {
|
||||
this.consultationId = consultationId;
|
||||
}
|
||||
public String getDiagnosis() {
|
||||
return diagnosis;
|
||||
}
|
||||
public void setDiagnosis(String diagnosis) {
|
||||
this.diagnosis = diagnosis;
|
||||
}
|
||||
public String getTreatment() {
|
||||
return treatment;
|
||||
}
|
||||
public void setTreatment(String treatment) {
|
||||
this.treatment = treatment;
|
||||
}
|
||||
public String getNotes() {
|
||||
return notes;
|
||||
}
|
||||
public void setNotes(String notes) {
|
||||
this.notes = notes;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.enums.ShiftType;
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
|
||||
public record NurseDTO(
|
||||
@NotBlank(message = "Name is required")
|
||||
String name,
|
||||
@NotBlank(message = "License number is required")
|
||||
String licenseNumber,
|
||||
@NotBlank(message = "Email is required")
|
||||
@Email(message = "Invalid email format")
|
||||
String email,
|
||||
@NotBlank(message = "Telephone is required")
|
||||
@Pattern(regexp = "^\\+[0-9]{1,15}$", message = "Invalid telephone format")
|
||||
String telephone,
|
||||
@NotNull(message = "Shift type is required")
|
||||
ShiftType shiftType
|
||||
) {}
|
||||
@ -0,0 +1,13 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public record NurseScheduleDTO(
|
||||
@NotNull(message = "Nurse ID is required")
|
||||
Long nurseId,
|
||||
@NotNull(message = "Start time is required")
|
||||
LocalDateTime startTime,
|
||||
@NotNull(message = "End time is required")
|
||||
LocalDateTime endTime
|
||||
) {}
|
||||
@ -0,0 +1,11 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
public record OperatingRoomDTO(
|
||||
@NotBlank(message = "Room number is required")
|
||||
String roomNumber,
|
||||
@NotNull(message = "Availability status is required")
|
||||
Boolean isAvailable
|
||||
) {}
|
||||
@ -0,0 +1,13 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public record OperatingRoomScheduleDTO(
|
||||
@NotNull(message = "Operating room ID is required")
|
||||
Long roomId,
|
||||
@NotNull(message = "Start time is required")
|
||||
LocalDateTime startTime,
|
||||
@NotNull(message = "End time is required")
|
||||
LocalDateTime endTime
|
||||
) {}
|
||||
@ -0,0 +1,23 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.OffsetDateTime;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.enums.PaymentMethod;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.enums.PaymentMethod;
|
||||
|
||||
public record PaymentDTO(
|
||||
Long consultationId,
|
||||
Long medicalRecordId,
|
||||
|
||||
@NotNull(message = "Amount cannot be null")
|
||||
BigDecimal amount,
|
||||
|
||||
@NotNull(message = "Payment method cannot be null")
|
||||
PaymentMethod paymentMethod,
|
||||
|
||||
@NotNull(message = "Payment date cannot be null")
|
||||
OffsetDateTime paymentDate
|
||||
) {}
|
||||
@ -0,0 +1,29 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos;
|
||||
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.util.UUID; // เพิ่มการ import สำหรับ UUID
|
||||
|
||||
/**
|
||||
* A data transfer object representing a prescription
|
||||
*
|
||||
* @author FlookSP
|
||||
* @version 1.2
|
||||
*/
|
||||
public record PrescriptionDTO(
|
||||
|
||||
@NotNull(message = "Medical record ID cannot be null")
|
||||
Long medicalRecordId,
|
||||
|
||||
// แก้ไขชนิดข้อมูลจาก Long เป็น UUID เพื่อให้สอดคล้องกับ InventoryItem
|
||||
@NotNull(message = "Inventory item ID cannot be null")
|
||||
UUID inventoryItemId,
|
||||
|
||||
@NotNull(message = "Quantity cannot be null")
|
||||
@Min(value = 1, message = "Quantity must be at least 1")
|
||||
Integer quantity,
|
||||
|
||||
@NotBlank(message = "Instructions cannot be blank")
|
||||
String instructions
|
||||
) {}
|
||||
@ -0,0 +1,32 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.Prescription;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.inventory.InventoryItem;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.MedicalRecord;
|
||||
|
||||
public record PrescriptionResponseDTO(
|
||||
UUID id, // เปลี่ยนจาก Long เป็น UUID
|
||||
Long medicalRecordId,
|
||||
UUID inventoryItemId,
|
||||
String itemName,
|
||||
Integer quantity,
|
||||
String instructions,
|
||||
OffsetDateTime createdAt,
|
||||
OffsetDateTime updatedAt
|
||||
) {
|
||||
public PrescriptionResponseDTO(Prescription prescription) {
|
||||
this(
|
||||
prescription.getId(),
|
||||
prescription.getMedicalRecord().getId(),
|
||||
prescription.getInventoryItem().getId(),
|
||||
prescription.getInventoryItem().getItemName(),
|
||||
prescription.getQuantity(),
|
||||
prescription.getInstructions(),
|
||||
prescription.getCreatedAt(),
|
||||
prescription.getUpdatedAt()
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos.auth;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
/**
|
||||
* Data Transfer Object for doctor registration.
|
||||
* This DTO contains the credentials to register a new user and
|
||||
* the verification data to link them to an existing doctor record.
|
||||
*/
|
||||
public class DoctorRegistrationDTO {
|
||||
|
||||
@NotBlank(message = "Username must not be blank")
|
||||
private String login;
|
||||
|
||||
@NotBlank(message = "Password must not be blank")
|
||||
@Size(min = 8, message = "Password must be at least 8 characters long")
|
||||
private String password;
|
||||
|
||||
@NotBlank(message = "CRM must not be blank")
|
||||
private String crm;
|
||||
|
||||
// Getters and Setters
|
||||
public String getLogin() {
|
||||
return login;
|
||||
}
|
||||
|
||||
public void setLogin(String login) {
|
||||
this.login = login;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getCrm() {
|
||||
return crm;
|
||||
}
|
||||
|
||||
public void setCrm(String crm) {
|
||||
this.crm = crm;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos.auth;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
|
||||
public record LinkPatientToUserDTO(
|
||||
|
||||
@NotNull(message = "Patient ID cannot be null")
|
||||
Long patientId,
|
||||
|
||||
@NotBlank(message = "Username cannot be blank")
|
||||
String username,
|
||||
|
||||
@NotBlank(message = "Password cannot be blank")
|
||||
String password,
|
||||
|
||||
@NotBlank(message = "CPF cannot be blank")
|
||||
@Pattern(regexp = "\\d{11}", message = "Invalid CPF format")
|
||||
String cpf
|
||||
) {}
|
||||
@ -0,0 +1,14 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos.auth;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
public record NurseRegistrationDTO(
|
||||
@NotBlank(message = "Login cannot be blank")
|
||||
String login,
|
||||
|
||||
@NotBlank(message = "Password cannot be blank")
|
||||
String password,
|
||||
|
||||
@NotBlank(message = "License number cannot be blank")
|
||||
String licenseNumber) {
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
// DTO สำหรับการลงทะเบียนผู้ป่วยขึ้นมาใหม่ และใช้ PatientDTO ที่มีอยู่เป็นส่วนประกอบ (Composition)
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos.auth;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.dtos.patient.PatientDTO;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
public record PatientRegistrationDTO(
|
||||
@NotBlank(message = "login cannot be blank")
|
||||
String login,
|
||||
|
||||
@NotBlank(message = "password cannot be blank")
|
||||
String password,
|
||||
|
||||
@NotNull(message = "patient data cannot be null")
|
||||
@Valid
|
||||
PatientDTO patientData
|
||||
) {}
|
||||
@ -0,0 +1,36 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos.auth;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.enums.Role;
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
|
||||
/**
|
||||
* A data transfer object representing staff registration data.
|
||||
*
|
||||
* @author FlookSP
|
||||
* @version 1.0
|
||||
*/
|
||||
public record StaffRegistrationDTO(
|
||||
|
||||
@NotBlank(message = "name cannot be blank")
|
||||
String name,
|
||||
|
||||
@NotBlank(message = "email cannot be blank")
|
||||
@Email(message = "email format is invalid")
|
||||
String email,
|
||||
|
||||
@NotBlank(message = "telephone cannot be blank")
|
||||
@Pattern(regexp = "^[0-9]{9,15}$", message = "telephone format is invalid")
|
||||
String telephone,
|
||||
|
||||
@NotBlank(message = "login cannot be blank")
|
||||
String login,
|
||||
|
||||
@NotBlank(message = "password cannot be blank")
|
||||
String password,
|
||||
|
||||
@NotNull(message = "role cannot be null")
|
||||
Role role
|
||||
) {}
|
||||
@ -0,0 +1,15 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos.auth;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
/**
|
||||
* A Data Transfer Object for updating a user's password.
|
||||
*
|
||||
* @author FlookSP
|
||||
* @version 1.0
|
||||
*/
|
||||
public record UserUpdatePasswordDTO(
|
||||
@NotBlank(message = "Password cannot be blank")
|
||||
String password
|
||||
) {}
|
||||
@ -0,0 +1,14 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos.auth;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* A Data Transfer Object for updating a user's role.
|
||||
*
|
||||
* @author FlookSP
|
||||
* @version 1.0
|
||||
*/
|
||||
public record UserUpdateRoleDTO(
|
||||
@NotBlank(message = "Role cannot be blank")
|
||||
String role
|
||||
) {}
|
||||
@ -0,0 +1,14 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos.auth;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* A Data Transfer Object for updating a user's login name.
|
||||
*
|
||||
* @author FlookSP
|
||||
* @version 1.0
|
||||
*/
|
||||
public record UserUpdateUsernameDTO(
|
||||
@NotBlank(message = "Username cannot be blank")
|
||||
String username
|
||||
) {}
|
||||
@ -1,36 +1,49 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos.consultation;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import java.time.OffsetDateTime;
|
||||
import com.mirna.hospitalmanagementapi.domain.enums.Specialty;
|
||||
import com.mirna.hospitalmanagementapi.domain.validators.consultation.constraints.ConsultationDateBusinessHours;
|
||||
import com.mirna.hospitalmanagementapi.domain.validators.consultation.constraints.ConsultationDateScheduledInAdvance;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import jakarta.validation.constraints.Future;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* Data transfer object used to transfer data that will be saved in a Consultation entity
|
||||
*
|
||||
* @author Mirna Gama
|
||||
* @version 1.0
|
||||
*/
|
||||
public record ConsultationDTO (
|
||||
* Data transfer object used to transfer data that will be saved in a Consultation entity
|
||||
* * @author Mirna Gama (Extended by FlookSP)
|
||||
* @version 1.0
|
||||
*/
|
||||
public record ConsultationDTO(
|
||||
|
||||
Long doctorId,
|
||||
@Schema(
|
||||
description = "รหัสแพทย์สำหรับจองโดยตรง (ไม่บังคับ) ต้องเป็น null หากระบุแผนก",
|
||||
example = "1"
|
||||
)
|
||||
Long doctorId,
|
||||
|
||||
@NotNull(message="patient id cannot be null")
|
||||
Long patientId,
|
||||
@Schema(
|
||||
description = "รหัสผู้ป่วยที่ต้องการนัดหมาย",
|
||||
example = "1"
|
||||
)
|
||||
@NotNull(message="patient id cannot be null")
|
||||
Long patientId,
|
||||
|
||||
@NotNull(message="consultation date cannot be null")
|
||||
@Future
|
||||
@JsonFormat(pattern = "dd/MM/yyyy HH:mm")
|
||||
@ConsultationDateScheduledInAdvance
|
||||
@ConsultationDateBusinessHours
|
||||
LocalDateTime consultationDate,
|
||||
@Schema(
|
||||
description = "วันที่และเวลาที่ต้องการนัดหมายในรูปแบบ ISO 8601 พร้อม timezone offset (+07:00 สำหรับประเทศไทย)",
|
||||
example = "2025-09-15T10:00:00+07:00"
|
||||
)
|
||||
@NotNull(message="consultation date cannot be null")
|
||||
@Future
|
||||
@ConsultationDateScheduledInAdvance
|
||||
@ConsultationDateBusinessHours
|
||||
OffsetDateTime consultationDate,
|
||||
|
||||
Specialty specialty
|
||||
@Schema(
|
||||
description = "แผนกที่ต้องการ (ไม่บังคับ) ต้องระบุหากไม่ได้ระบุรหัสแพทย์",
|
||||
example = "ORTHOPEDICS"
|
||||
)
|
||||
Specialty specialty
|
||||
) {
|
||||
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos.inventory;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.enums.TransactionType;
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
// ปรับปรุง InventoryItemDTO: ย้ายแพ็กเกจและใช้ Lombok
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class InventoryItemDTO {
|
||||
@NotNull(message = "Item Type ID cannot be null")
|
||||
private UUID itemTypeId;
|
||||
|
||||
@NotNull(message = "Supplier ID cannot be null")
|
||||
private UUID supplierId;
|
||||
|
||||
@NotBlank(message = "Item name cannot be blank")
|
||||
private String itemName;
|
||||
|
||||
private String description;
|
||||
|
||||
private Integer currentStock;
|
||||
|
||||
private String serialNumber;
|
||||
|
||||
@NotBlank(message = "Unit of measure cannot be blank")
|
||||
private String unitOfMeasure;
|
||||
|
||||
private BigDecimal unitPrice;
|
||||
private Integer reorderLevel;
|
||||
private LocalDate expirationDate;
|
||||
private String location;
|
||||
private Boolean isActive;
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos.inventory;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.inventory.InventoryItem;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.inventory.InventoryItemType;
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.inventory.InventorySupplier;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.UUID;
|
||||
import java.math.BigDecimal; // Import BigDecimal
|
||||
|
||||
public class InventoryItemResponseDTO {
|
||||
|
||||
private UUID id;
|
||||
private String itemName;
|
||||
private String description;
|
||||
private Integer currentStock;
|
||||
private String unitOfMeasure;
|
||||
private BigDecimal unitPrice; // ใช้ BigDecimal เพื่อความแม่นยำ
|
||||
private Integer reorderLevel;
|
||||
private LocalDate expirationDate;
|
||||
private String location;
|
||||
private Boolean isActive;
|
||||
|
||||
private InventoryItemTypeResponseDTO itemType;
|
||||
private SupplierResponseDTO supplier;
|
||||
|
||||
public InventoryItemResponseDTO(InventoryItem entity) {
|
||||
this.id = entity.getId();
|
||||
this.itemName = entity.getItemName();
|
||||
this.description = entity.getDescription();
|
||||
this.currentStock = entity.getCurrentStock();
|
||||
this.unitOfMeasure = entity.getUnitOfMeasure();
|
||||
this.unitPrice = entity.getUnitPrice();
|
||||
this.reorderLevel = entity.getReorderLevel();
|
||||
this.expirationDate = entity.getExpirationDate();
|
||||
this.location = entity.getLocation();
|
||||
this.isActive = entity.getIsActive();
|
||||
|
||||
if (entity.getItemType() != null) {
|
||||
this.itemType = new InventoryItemTypeResponseDTO(entity.getItemType());
|
||||
}
|
||||
if (entity.getSupplier() != null) {
|
||||
this.supplier = new SupplierResponseDTO(entity.getSupplier());
|
||||
}
|
||||
}
|
||||
|
||||
// Getters
|
||||
public UUID getId() { return id; }
|
||||
public String getItemName() { return itemName; }
|
||||
public String getDescription() { return description; }
|
||||
public Integer getCurrentStock() { return currentStock; }
|
||||
public String getUnitOfMeasure() { return unitOfMeasure; }
|
||||
public BigDecimal getUnitPrice() { return unitPrice; }
|
||||
public Integer getReorderLevel() { return reorderLevel; }
|
||||
public LocalDate getExpirationDate() { return expirationDate; }
|
||||
public String getLocation() { return location; }
|
||||
public Boolean getIsActive() { return isActive; }
|
||||
public InventoryItemTypeResponseDTO getItemType() { return itemType; }
|
||||
public SupplierResponseDTO getSupplier() { return supplier; }
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos.inventory;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.inventory.InventoryItemType;
|
||||
import java.util.UUID;
|
||||
|
||||
public class InventoryItemTypeResponseDTO {
|
||||
|
||||
private UUID id;
|
||||
private String typeName;
|
||||
|
||||
public InventoryItemTypeResponseDTO(InventoryItemType entity) {
|
||||
this.id = entity.getId();
|
||||
this.typeName = entity.getTypeName();
|
||||
}
|
||||
|
||||
// Getters
|
||||
public UUID getId() { return id; }
|
||||
public String getTypeName() { return typeName; }
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos.inventory;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.enums.TransactionType;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import java.util.UUID;
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
// ปรับปรุง InventoryTransactionDTO: ใช้ Lombok และเพิ่มการรับค่า transactionDate
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class InventoryTransactionDTO {
|
||||
@NotNull(message = "Item ID cannot be null")
|
||||
private UUID itemId;
|
||||
|
||||
@NotNull(message = "Transaction Type cannot be null")
|
||||
private TransactionType transactionType;
|
||||
|
||||
@NotNull(message = "Quantity cannot be null")
|
||||
@Min(value = 1, message = "Quantity must be at least 1")
|
||||
private Integer quantity;
|
||||
|
||||
private UUID relatedDocumentId;
|
||||
private String notes;
|
||||
private ZonedDateTime transactionDate; // เพิ่ม field นี้เพื่อความยืดหยุ่นในการทดสอบ
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos.inventory;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.inventory.InventoryItem;
|
||||
import java.util.UUID;
|
||||
|
||||
public class InventoryTransactionItemResponseDTO {
|
||||
private UUID id;
|
||||
private String itemName;
|
||||
private String unitOfMeasure;
|
||||
|
||||
public InventoryTransactionItemResponseDTO(InventoryItem entity) {
|
||||
this.id = entity.getId();
|
||||
this.itemName = entity.getItemName();
|
||||
this.unitOfMeasure = entity.getUnitOfMeasure();
|
||||
}
|
||||
|
||||
// Getters and setters (คุณอาจใช้ @Data หรือ @Value จาก Lombok เพื่อลดโค้ด)
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getItemName() {
|
||||
return itemName;
|
||||
}
|
||||
|
||||
public void setItemName(String itemName) {
|
||||
this.itemName = itemName;
|
||||
}
|
||||
|
||||
public String getUnitOfMeasure() {
|
||||
return unitOfMeasure;
|
||||
}
|
||||
|
||||
public void setUnitOfMeasure(String unitOfMeasure) {
|
||||
this.unitOfMeasure = unitOfMeasure;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,96 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos.inventory;
|
||||
|
||||
import com.mirna.hospitalmanagementapi.domain.entities.inventory.InventoryTransaction;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
public class InventoryTransactionResponseDTO {
|
||||
|
||||
private UUID id;
|
||||
|
||||
@JsonProperty("item")
|
||||
private InventoryTransactionItemResponseDTO item;
|
||||
|
||||
private String transactionType;
|
||||
|
||||
private Integer quantity;
|
||||
|
||||
private UUID relatedDocumentId;
|
||||
|
||||
private String notes;
|
||||
|
||||
private ZonedDateTime transactionDate;
|
||||
|
||||
public InventoryTransactionResponseDTO(InventoryTransaction entity) {
|
||||
this.id = entity.getId();
|
||||
// แปลง enum เป็น String
|
||||
this.transactionType = entity.getTransactionType().toString();
|
||||
this.quantity = entity.getQuantity();
|
||||
this.relatedDocumentId = entity.getRelatedDocumentId();
|
||||
this.notes = entity.getNotes();
|
||||
this.transactionDate = entity.getTransactionDate();
|
||||
|
||||
// Map related item to a simplified DTO
|
||||
if (entity.getItem() != null) {
|
||||
this.item = new InventoryTransactionItemResponseDTO(entity.getItem());
|
||||
}
|
||||
}
|
||||
|
||||
// Getters and setters (คุณอาจใช้ @Data หรือ @Value จาก Lombok เพื่อลดโค้ด)
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public InventoryTransactionItemResponseDTO getItem() {
|
||||
return item;
|
||||
}
|
||||
|
||||
public void setItem(InventoryTransactionItemResponseDTO item) {
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
public String getTransactionType() {
|
||||
return transactionType;
|
||||
}
|
||||
|
||||
public void setTransactionType(String transactionType) {
|
||||
this.transactionType = transactionType;
|
||||
}
|
||||
|
||||
public Integer getQuantity() {
|
||||
return quantity;
|
||||
}
|
||||
|
||||
public void setQuantity(Integer quantity) {
|
||||
this.quantity = quantity;
|
||||
}
|
||||
|
||||
public UUID getRelatedDocumentId() {
|
||||
return relatedDocumentId;
|
||||
}
|
||||
|
||||
public void setRelatedDocumentId(UUID relatedDocumentId) {
|
||||
this.relatedDocumentId = relatedDocumentId;
|
||||
}
|
||||
|
||||
public String getNotes() {
|
||||
return notes;
|
||||
}
|
||||
|
||||
public void setNotes(String notes) {
|
||||
this.notes = notes;
|
||||
}
|
||||
|
||||
public ZonedDateTime getTransactionDate() {
|
||||
return transactionDate;
|
||||
}
|
||||
|
||||
public void setTransactionDate(ZonedDateTime transactionDate) {
|
||||
this.transactionDate = transactionDate;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos.inventory;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ItemTypeDTO {
|
||||
|
||||
@NotBlank(message = "ชื่อประเภทรายการสินค้าห้ามว่าง")
|
||||
@Size(max = 50, message = "ชื่อประเภทรายการสินค้ามีความยาวได้สูงสุด 50 ตัวอักษร")
|
||||
private String name;
|
||||
|
||||
@Size(max = 500, message = "คำอธิบายมีความยาวได้สูงสุด 500 ตัวอักษร")
|
||||
private String description;
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package com.mirna.hospitalmanagementapi.domain.dtos.inventory;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SupplierDTO {
|
||||
|
||||
@NotBlank(message = "ชื่อผู้จำหน่ายห้ามว่าง")
|
||||
@Size(max = 100, message = "ชื่อผู้จำหน่ายมีความยาวได้สูงสุด 100 ตัวอักษร")
|
||||
private String supplierName;
|
||||
|
||||
@Size(max = 100, message = "ชื่อผู้ติดต่อมีความยาวได้สูงสุด 100 ตัวอักษร")
|
||||
private String contactPerson;
|
||||
|
||||
@Email(message = "รูปแบบอีเมลไม่ถูกต้อง")
|
||||
@Size(max = 100, message = "อีเมลมีความยาวได้สูงสุด 100 ตัวอักษร")
|
||||
private String contactEmail;
|
||||
|
||||
@Size(max = 20, message = "เบอร์โทรศัพท์มีความยาวได้สูงสุด 20 ตัวอักษร")
|
||||
private String phoneNumber;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user