Initial commit - Extended Hospital Management API v2.0
This commit is contained in:
parent
c372590e28
commit
5db80d5299
2
.gitignore
vendored
2
.gitignore
vendored
@ -31,3 +31,5 @@ build/
|
|||||||
|
|
||||||
### VS Code ###
|
### VS Code ###
|
||||||
.vscode/
|
.vscode/
|
||||||
|
|
||||||
|
.env
|
||||||
18
Dockerfile
18
Dockerfile
@ -1,4 +1,14 @@
|
|||||||
FROM eclipse-temurin:17-jdk-alpine
|
# ใช้ JRE เป็น base image เพื่อลดขนาด image
|
||||||
VOLUME /tmp
|
FROM eclipse-temurin:17-jre-jammy
|
||||||
COPY target/*.jar /app/hospital-management-api.jar
|
|
||||||
ENTRYPOINT ["java", "-jar","/app/hospital-management-api.jar"]
|
# กำหนด 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"]
|
||||||
|
|||||||
855
README.md
855
README.md
@ -1,633 +1,286 @@
|
|||||||
# Hospital Management - API Module 
|
# Hospital Management API (Extended Version)
|
||||||
|
|
||||||
## About the project
|

|
||||||
Hospital Management API built in Spring Boot
|

|
||||||
|
|
||||||
### Prerequisites:
|
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.
|
||||||
- Spring Boot 3.2.1
|
|
||||||
- JDK 17
|
|
||||||
- Maven 4.0.0
|
|
||||||
|
|
||||||
### Running the application
|
---
|
||||||
1. `git clone https://github.com/MirnaGama/hospital-management-api/`
|
|
||||||
2. `cd hospital-management-api`
|
|
||||||
3. `mvn clean install`<br>
|
|
||||||
It will build the jar file in the target folder
|
|
||||||
4. `mvn spring-boot:run`<br>
|
|
||||||
It will compile and run the application on default port (8080)
|
|
||||||
|
|
||||||
### Running tests
|
## ✨ Improvements and New Features
|
||||||
- `mvn test`<br>
|
|
||||||
It will executes all the tests.
|
|
||||||
|
|
||||||
- `mvn -Dtest=packageName.className test`<br>
|
### 1. Code Structure and Architecture
|
||||||
It will execute only one test class
|
|
||||||
|
|
||||||
- `mvn -Dtest=packageName.className#methodName test`<br>
|
* **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.
|
||||||
It will run only one test method from one test class
|
* **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.
|
||||||
|
|
||||||
### Features - v1.0
|
### 2. Endpoint and Data Handling Changes
|
||||||
- [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
|
|
||||||
- [X] R10 - Consultation Cancellation
|
|
||||||
|
|
||||||
## API Documentation - /swagger-ui/index.html
|
* **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.
|
||||||
|
|
||||||
### authentication
|
### 3. Major Test Suite Refinement
|
||||||
|
|
||||||
#### POST - [**/api/auth/register**] - Register a new user
|
* **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.
|
||||||
|
|
||||||
- **Body:**
|
### 4. Additional Features
|
||||||
```
|
|
||||||
{
|
* Refined the user and patient registration flow.
|
||||||
"login" (string, required),
|
* Introduced **RBAC (Role-Based Access Control)** to manage system permissions.
|
||||||
"password" (string, required),
|
* 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 |
|
เปิด IntelliJ → ไปที่ Run → Edit Configurations
|
||||||
| ------------- | ------------- |
|
|
||||||
| `200` | _Successful operation_ |
|
|
||||||
| `400` | _Validation Error_ |
|
|
||||||
|
|
||||||
#### POST - [**/api/auth/login**] - Perform the login
|
เลือก Configuration ของ Spring Boot ของโปรเจค
|
||||||
|
|
||||||
- **Body:**
|
ในส่วน Environment Variables กำหนดค่าตามนี้:
|
||||||
```
|
```
|
||||||
{
|
POSTGRES_HOST=localhost
|
||||||
"login" (string, required),
|
POSTGRES_PORT=5432
|
||||||
"password" (string, required),
|
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:**
|
### 3️⃣ Run PostgreSQL and pgAdmin
|
||||||
|
|
||||||
| Code | Description |
|
|
||||||
| ------------- | ------------- |
|
|
||||||
| `200` | _Successful operation_ |
|
|
||||||
| `400` | _Validation Error_ |
|
|
||||||
| `403` | _Incorrect credentials_ |
|
|
||||||
|
|
||||||
|
|
||||||
### doctors
|
|
||||||
|
|
||||||
#### POST - [**/api/v1.0/doctors**] - Adds a new doctor
|
|
||||||
|
|
||||||
- **Body:**
|
|
||||||
```
|
```
|
||||||
{
|
# รันเฉพาะ PostgreSQL และ pgAdmin
|
||||||
"name" (string, required),
|
docker-compose up -d postgresdb pgadmin
|
||||||
"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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
- **Request Headers:**
|
### 4️⃣ Run Spring Boot Application
|
||||||
|
|
||||||
| Key | Description |
|
เปิด IntelliJ
|
||||||
| ------------- | ------------- |
|
|
||||||
| `Authorization` | _Authorization token_ |
|
|
||||||
|
|
||||||
- **Responses:**
|
Run Spring Boot จาก Configuration ที่ตั้งค่า Environment Variables แล้ว
|
||||||
|
|
||||||
| Code | Description |
|
✅ แอปจะเชื่อมต่อ PostgreSQL และ MinIO ตามค่าที่กำหนด
|
||||||
| ------------- | ------------- |
|
|
||||||
| `201` | _Successfully created_ |
|
|
||||||
| `400` | _Validation Error_ |
|
|
||||||
| `403` | _Unauthorized / Invalid token_ |
|
|
||||||
|
|
||||||
#### GET - [**/api/v1.0/doctors/{id}**] - Get an existing doctor
|
---
|
||||||
|
|
||||||
- **Response Body Example:**
|
### Future Development Plan (v2.1+)
|
||||||
```
|
|
||||||
{
|
|
||||||
"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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Request Headers:**
|
We will continue to develop on Spring Boot following standard best practices to add the following capabilities:
|
||||||
|
|
||||||
| Key | Description |
|
**AI-Driven Enhancements**
|
||||||
| ------------- | ------------- |
|
- Implement predictive analytics for patient admissions and resource allocation.
|
||||||
| `Authorization` | _Authorization token_ |
|
- 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:**
|
## 🙏 Credits
|
||||||
|
Extended version of MirnaGama/hospital-management-api.
|
||||||
| Code | Description |
|
This continuation improves code quality, adds features, and addresses real-world issues.
|
||||||
| ------------- | ------------- |
|
|
||||||
| `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 |
|
|
||||||
| ------------- | ------------- |
|
|
||||||
| `201` | _Successfully created_ |
|
|
||||||
| `400` | _Validation Error_ |
|
|
||||||
| `403` | _Unauthorized / Invalid token_ |
|
|
||||||
| `404` | _Entity not found_ |
|
|
||||||
|
|
||||||
#### GET - [**/api/v1.0/consultations/{id}**] - Get an existing consultation
|
|
||||||
|
|
||||||
- **Response Body Example:**
|
|
||||||
```
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"consultationDate": "22/04/2024 10:34",
|
|
||||||
"patient": {...},
|
|
||||||
"doctor": {...},
|
|
||||||
"canceled": false,
|
|
||||||
"reasonCancellation: ""
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Request Headers:**
|
|
||||||
|
|
||||||
| Key | Description |
|
|
||||||
| ------------- | ------------- |
|
|
||||||
| `Authorization` | _Authorization token_ |
|
|
||||||
|
|
||||||
- **Request Parameters:**
|
|
||||||
|
|
||||||
| Key | Description |
|
|
||||||
| ------------- | ------------- |
|
|
||||||
| `id` | _Unique identifier of the consultation that will be fetched_ |
|
|
||||||
|
|
||||||
- **Responses:**
|
|
||||||
|
|
||||||
| Code | Description |
|
|
||||||
| ------------- | ------------- |
|
|
||||||
| `200` | _Successful operation_ |
|
|
||||||
| `404` | _Entity not found_ |
|
|
||||||
| `403` | _Unauthorized / Invalid token_ |
|
|
||||||
|
|
||||||
#### DELETE - [**/api/v1.0/consultations**] - Cancels a scheduled consultation
|
|
||||||
|
|
||||||
- **Body:**
|
|
||||||
```
|
|
||||||
{
|
|
||||||
"consultationId" (number, required),
|
|
||||||
"reasonCancellation" (string, required),
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- **Request Headers:**
|
|
||||||
|
|
||||||
| Key | Description |
|
|
||||||
| ------------- | ------------- |
|
|
||||||
| `Authorization` | _Authorization token_ |
|
|
||||||
|
|
||||||
- **Responses:**
|
|
||||||
|
|
||||||
| Code | Description |
|
|
||||||
| ------------- | ------------- |
|
|
||||||
| `200` | _Successful operation_ |
|
|
||||||
| `403` | _Unauthorized / Invalid token_ |
|
|
||||||
| `404` | _Entity not found_ |
|
|
||||||
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:
|
||||||
32
pom.xml
32
pom.xml
@ -41,22 +41,36 @@
|
|||||||
<artifactId>spring-boot-starter-validation</artifactId>
|
<artifactId>spring-boot-starter-validation</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.flywaydb</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
<artifactId>flyway-core</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>1.18.30</version>
|
||||||
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- PostgreSQL JDBC Driver -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.flywaydb</groupId>
|
<groupId>org.postgresql</groupId>
|
||||||
<artifactId>flyway-mysql</artifactId>
|
<artifactId>postgresql</artifactId>
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.mysql</groupId>
|
|
||||||
<artifactId>mysql-connector-j</artifactId>
|
|
||||||
<scope>runtime</scope>
|
<scope>runtime</scope>
|
||||||
</dependency>
|
</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>
|
<dependency>
|
||||||
<groupId>com.h2database</groupId>
|
<groupId>com.h2database</groupId>
|
||||||
<artifactId>h2</artifactId>
|
<artifactId>h2</artifactId>
|
||||||
<version>2.1.214</version>
|
<version>2.2.220</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<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.exceptions.ConsultationValidationException;
|
||||||
import com.mirna.hospitalmanagementapi.domain.services.ConsultationService;
|
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 io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
|
|
||||||
@ -43,13 +47,40 @@ public class ConsultationController {
|
|||||||
*
|
*
|
||||||
* @param consultationDTO The data transfer object containing data for Consultation
|
* @param consultationDTO The data transfer object containing data for Consultation
|
||||||
* entity.
|
* entity.
|
||||||
*
|
* * @return A response entity containing the saved consultation and created status if successful, or
|
||||||
* @return A response entity containing the saved consultation and created status if successful, or
|
|
||||||
* a 400-level error if there is a validation error
|
* a 400-level error if there is a validation error
|
||||||
* @throws ConsultationValidationException if there is a validation error
|
* @throws ConsultationValidationException if there is a validation error
|
||||||
*/
|
*/
|
||||||
@PostMapping
|
@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 {
|
public ResponseEntity<Object> postConsultation(@RequestBody @Valid ConsultationDTO consultationDTO) throws ConsultationValidationException {
|
||||||
|
System.out.println("--- Inside ConsultationController.postConsultation ---");
|
||||||
|
System.out.println("Received DTO: " + consultationDTO.toString());
|
||||||
|
|
||||||
Consultation consultation = consultationService.addConsultation(consultationDTO);
|
Consultation consultation = consultationService.addConsultation(consultationDTO);
|
||||||
|
|
||||||
UriComponents uriComponents = UriComponentsBuilder
|
UriComponents uriComponents = UriComponentsBuilder
|
||||||
@ -66,8 +97,7 @@ public class ConsultationController {
|
|||||||
* Get method to receive a Consultation record by the provided ID
|
* Get method to receive a Consultation record by the provided ID
|
||||||
*
|
*
|
||||||
* @param id A long representing the consultation's unique identifier
|
* @param id A long representing the consultation's unique identifier
|
||||||
*
|
* * @return A response entity containing the corresponding consultation if successful, or
|
||||||
* @return A response entity containing the corresponding consultation if successful, or
|
|
||||||
* a 400-level error if it is non-existent
|
* a 400-level error if it is non-existent
|
||||||
*/
|
*/
|
||||||
@GetMapping("/{id}")
|
@GetMapping("/{id}")
|
||||||
@ -82,8 +112,7 @@ public class ConsultationController {
|
|||||||
*
|
*
|
||||||
* @param consultationCanceledDTO The data transfer object containing data to update Consultation
|
* @param consultationCanceledDTO The data transfer object containing data to update Consultation
|
||||||
* entity.
|
* entity.
|
||||||
*
|
* * @return A response entity containing the canceled consultation and ok status if successful, or
|
||||||
* @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
|
* a 400-level error if the consultation entity is not found
|
||||||
*/
|
*/
|
||||||
@DeleteMapping
|
@DeleteMapping
|
||||||
|
|||||||
@ -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;
|
package com.mirna.hospitalmanagementapi.application.controllers.auth;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
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.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
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.entities.auth.User;
|
||||||
import com.mirna.hospitalmanagementapi.domain.services.auth.AuthService;
|
import com.mirna.hospitalmanagementapi.domain.services.auth.AuthService;
|
||||||
import com.mirna.hospitalmanagementapi.domain.services.auth.jwt.TokenService;
|
import com.mirna.hospitalmanagementapi.domain.services.auth.jwt.TokenService;
|
||||||
|
import com.mirna.hospitalmanagementapi.domain.services.PatientService;
|
||||||
|
|
||||||
import jakarta.validation.Valid;
|
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.
|
* A Spring REST controller for managing authentication and user information.
|
||||||
@ -33,19 +51,21 @@ public class AuthenticationController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private TokenService tokenService;
|
private TokenService tokenService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PatientService patientService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs the user login
|
* Performs the user login
|
||||||
*
|
*
|
||||||
* @param userDTO A data transfer object containing the user data to perform the 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.
|
||||||
* @return The authorization token if successful, or an unauthorized status if there is an error.
|
|
||||||
*/
|
*/
|
||||||
@PostMapping(value = "/login")
|
@PostMapping(value = "/login")
|
||||||
public ResponseEntity<Object> login(@RequestBody @Valid UserDTO userDTO) {
|
public ResponseEntity<Object> login(@RequestBody @Valid UserDTO userDTO) {
|
||||||
|
|
||||||
Authentication auth = authService.login(userDTO);
|
var auth = authService.login(userDTO);
|
||||||
|
|
||||||
User authenticatedUser = (User) auth.getPrincipal();
|
var authenticatedUser = (User) auth.getPrincipal();
|
||||||
|
|
||||||
String token = tokenService.generateToken(authenticatedUser);
|
String token = tokenService.generateToken(authenticatedUser);
|
||||||
|
|
||||||
@ -56,16 +76,95 @@ public class AuthenticationController {
|
|||||||
* Performs the user registration
|
* Performs the user registration
|
||||||
*
|
*
|
||||||
* @param userDTO A data transfer object containing the user data to perform the 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 The registered user if successful, or null if there is an error.
|
|
||||||
*/
|
*/
|
||||||
|
/*@PostMapping(value = "/register")
|
||||||
@PostMapping(value = "/register")
|
|
||||||
public ResponseEntity<Object> register(@RequestBody @Valid UserDTO userDTO) {
|
public ResponseEntity<Object> register(@RequestBody @Valid UserDTO userDTO) {
|
||||||
|
|
||||||
User user = authService.register(userDTO);
|
User user = authService.register(userDTO);
|
||||||
|
return ResponseEntity.ok(user);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
package com.mirna.hospitalmanagementapi.application.services;
|
||||||
|
|
||||||
import org.apache.coyote.BadRequestException;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
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.FindConsultationByIdUseCase;
|
||||||
import com.mirna.hospitalmanagementapi.application.usecase.consultation.FindConsultationByPatientAndDateUseCase;
|
|
||||||
import com.mirna.hospitalmanagementapi.application.usecase.consultation.SaveConsultationUseCase;
|
import com.mirna.hospitalmanagementapi.application.usecase.consultation.SaveConsultationUseCase;
|
||||||
import com.mirna.hospitalmanagementapi.application.usecase.doctor.FindDoctorByIdUseCase;
|
import com.mirna.hospitalmanagementapi.application.usecase.doctor.FindDoctorByIdUseCase;
|
||||||
import com.mirna.hospitalmanagementapi.application.usecase.doctor.FindOneFreeDoctorBySpecialtyUseCase;
|
import com.mirna.hospitalmanagementapi.application.usecase.doctor.FindOneFreeDoctorBySpecialtyUseCase;
|
||||||
@ -18,17 +14,16 @@ import com.mirna.hospitalmanagementapi.domain.entities.Doctor;
|
|||||||
import com.mirna.hospitalmanagementapi.domain.entities.Patient;
|
import com.mirna.hospitalmanagementapi.domain.entities.Patient;
|
||||||
import com.mirna.hospitalmanagementapi.domain.exceptions.ConsultationValidationException;
|
import com.mirna.hospitalmanagementapi.domain.exceptions.ConsultationValidationException;
|
||||||
import com.mirna.hospitalmanagementapi.domain.services.ConsultationService;
|
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 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
|
@Service
|
||||||
public class ConsultationServiceImpl implements ConsultationService {
|
public class ConsultationServiceImpl implements ConsultationService {
|
||||||
|
|
||||||
@ -39,10 +34,7 @@ public class ConsultationServiceImpl implements ConsultationService {
|
|||||||
private FindConsultationByIdUseCase findConsultationById;
|
private FindConsultationByIdUseCase findConsultationById;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private FindConsultationByDoctorAndDateUseCase findConsultationByDoctorAndDate;
|
private ConsultationRepository consultationRepository;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private FindConsultationByPatientAndDateUseCase findConsultationByPatientAndDate;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private FindPatientByIdUseCase findPatientById;
|
private FindPatientByIdUseCase findPatientById;
|
||||||
@ -53,58 +45,88 @@ public class ConsultationServiceImpl implements ConsultationService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private FindOneFreeDoctorBySpecialtyUseCase findOneFreeDoctorBySpecialty;
|
private FindOneFreeDoctorBySpecialtyUseCase findOneFreeDoctorBySpecialty;
|
||||||
|
|
||||||
/**
|
@Autowired
|
||||||
* Adds a new consultation to the repository.
|
private DoctorScheduleService doctorScheduleService;
|
||||||
*
|
|
||||||
* @param consultationDTO A data transfer object representing a consultation to add.
|
private static final ZoneOffset BANGKOK_ZONE_OFFSET = ZoneOffset.ofHours(7);
|
||||||
* @return The saved consultation if successful, or throws an exception if there is an error.
|
|
||||||
* @throws ConsultationValidationException if there is a validation error
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
|
@Transactional
|
||||||
public Consultation addConsultation(ConsultationDTO consultationDTO) throws ConsultationValidationException {
|
public Consultation addConsultation(ConsultationDTO consultationDTO) throws ConsultationValidationException {
|
||||||
|
Patient patient = validatePatient(consultationDTO.patientId(), consultationDTO.consultationDate());
|
||||||
Patient patient = findPatientById.execute(consultationDTO.patientId());
|
Doctor doctor = validateAndFindDoctor(consultationDTO);
|
||||||
|
validatePatientAndDoctorAvailability(patient, doctor, consultationDTO.consultationDate());
|
||||||
if (!patient.getActive())
|
|
||||||
throw new ConsultationValidationException("This patient is not active");
|
|
||||||
|
|
||||||
if (findConsultationByPatientAndDate.execute(patient.getId(), consultationDTO.consultationDate()) != null)
|
|
||||||
throw new ConsultationValidationException("This patient is not free on this date");
|
|
||||||
|
|
||||||
Doctor doctor = null;
|
|
||||||
|
|
||||||
if (consultationDTO.doctorId() != null) {
|
|
||||||
|
|
||||||
doctor = findDoctorById.execute(consultationDTO.doctorId());
|
|
||||||
|
|
||||||
if (!doctor.getActive())
|
|
||||||
throw new ConsultationValidationException("This doctor is not active");
|
|
||||||
|
|
||||||
if (findConsultationByDoctorAndDate.execute(doctor.getId(), consultationDTO.consultationDate()) != null)
|
|
||||||
throw new ConsultationValidationException("This doctor is not free on this date");
|
|
||||||
|
|
||||||
} else if (consultationDTO.specialty() != null) {
|
|
||||||
|
|
||||||
doctor = findOneFreeDoctorBySpecialty.execute(consultationDTO.specialty(),
|
|
||||||
consultationDTO.consultationDate());
|
|
||||||
|
|
||||||
if (doctor == null) throw new ConsultationValidationException("There is no free doctor for this date with this specialty");
|
|
||||||
|
|
||||||
} else {
|
|
||||||
throw new ConsultationValidationException("At least the specialty or doctor ID must be filled in");
|
|
||||||
}
|
|
||||||
|
|
||||||
Consultation consultation = new Consultation(patient, doctor, consultationDTO.consultationDate());
|
Consultation consultation = new Consultation(patient, doctor, consultationDTO.consultationDate());
|
||||||
|
|
||||||
return saveConsultation.execute(consultation);
|
return saveConsultation.execute(consultation);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private Patient validatePatient(Long patientId, OffsetDateTime consultationDate) throws ConsultationValidationException {
|
||||||
* Finds a stored consultation by id.
|
if (patientId == null) {
|
||||||
*
|
throw new ConsultationValidationException("Patient ID cannot be null");
|
||||||
* @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.
|
|
||||||
*/
|
Patient patient = findPatientById.execute(patientId);
|
||||||
|
|
||||||
|
if (patient == null) {
|
||||||
|
throw new ConsultationValidationException("This patient is not found");
|
||||||
|
}
|
||||||
|
if (!patient.getActive()) {
|
||||||
|
throw new ConsultationValidationException("This patient is not active");
|
||||||
|
}
|
||||||
|
|
||||||
|
OffsetDateTime consultationDateInBkkZone = consultationDate.withOffsetSameInstant(BANGKOK_ZONE_OFFSET);
|
||||||
|
OffsetDateTime startOfDay = consultationDateInBkkZone.with(LocalTime.MIN);
|
||||||
|
OffsetDateTime endOfDay = consultationDateInBkkZone.with(LocalTime.MAX);
|
||||||
|
|
||||||
|
// แก้ไขบรรทัดนี้: ส่งพารามิเตอร์ที่ถูกต้องไปยัง Repository
|
||||||
|
if (consultationRepository.findConsultationByPatientAndDate(patient.getId(), startOfDay, endOfDay) != null) {
|
||||||
|
throw new ConsultationValidationException("This patient is not free on this date");
|
||||||
|
}
|
||||||
|
return patient;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Doctor validateAndFindDoctor(ConsultationDTO consultationDTO) throws ConsultationValidationException {
|
||||||
|
Doctor doctor = null;
|
||||||
|
OffsetDateTime consultationDateInBkkZone = consultationDTO.consultationDate().withOffsetSameInstant(BANGKOK_ZONE_OFFSET);
|
||||||
|
|
||||||
|
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("No doctors found at the requested time or specialty.");
|
||||||
|
}
|
||||||
|
return doctor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validatePatientAndDoctorAvailability(Patient patient, Doctor doctor, OffsetDateTime consultationDate) throws ConsultationValidationException {
|
||||||
|
OffsetDateTime consultationDateInBkkZone = consultationDate.withOffsetSameInstant(BANGKOK_ZONE_OFFSET);
|
||||||
|
|
||||||
|
OffsetDateTime startOfDay = consultationDateInBkkZone.with(LocalTime.MIN);
|
||||||
|
OffsetDateTime endOfDay = consultationDateInBkkZone.with(LocalTime.MAX);
|
||||||
|
|
||||||
|
// แก้ไขบรรทัดนี้: ส่งพารามิเตอร์ที่ถูกต้องไปยัง Repository
|
||||||
|
if (consultationRepository.findConsultationByDoctorAndDate(doctor.getId(), startOfDay, endOfDay) != null) {
|
||||||
|
throw new ConsultationValidationException("This doctor is not free on this date");
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isDoctorAvailable = doctorScheduleService.isDoctorAvailable(
|
||||||
|
doctor.getId(),
|
||||||
|
consultationDateInBkkZone.getDayOfWeek(),
|
||||||
|
consultationDateInBkkZone.toLocalTime()
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!isDoctorAvailable) {
|
||||||
|
throw new ConsultationValidationException("The selected doctor is not on duty at the requested time.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Consultation findConsultationById(Long id) {
|
public Consultation findConsultationById(Long id) {
|
||||||
Consultation consultation = findConsultationById.execute(id);
|
Consultation consultation = findConsultationById.execute(id);
|
||||||
@ -115,19 +137,11 @@ public class ConsultationServiceImpl implements ConsultationService {
|
|||||||
return consultation;
|
return consultation;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
@Override
|
||||||
public Consultation cancelConsultation(ConsultationCanceledDTO consultationCanceledDTO) {
|
public Consultation cancelConsultation(ConsultationCanceledDTO consultationCanceledDTO) {
|
||||||
Consultation consultation = this.findConsultationById(consultationCanceledDTO.consultationId());
|
Consultation consultation = this.findConsultationById(consultationCanceledDTO.consultationId());
|
||||||
|
|
||||||
consultation.setCanceled(true);
|
consultation.setCanceled(true);
|
||||||
consultation.setReasonCancellation(consultationCanceledDTO.reasonCancellation());
|
consultation.setReasonCancellation(consultationCanceledDTO.reasonCancellation());
|
||||||
|
|
||||||
return saveConsultation.execute(consultation);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -105,7 +105,7 @@ public class DoctorServiceImpl implements DoctorService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (doctorUpdatedDataDTO.telephone() != null) {
|
if (doctorUpdatedDataDTO.telephone() != null) {
|
||||||
doctor.setName(doctorUpdatedDataDTO.telephone());
|
doctor.setTelephone(doctorUpdatedDataDTO.telephone());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doctorUpdatedDataDTO.address() != null) {
|
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.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.stereotype.Service;
|
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.FindPatientByIdUseCase;
|
||||||
import com.mirna.hospitalmanagementapi.application.usecase.patient.FindPatientsUseCase;
|
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.Address;
|
||||||
import com.mirna.hospitalmanagementapi.domain.entities.Patient;
|
import com.mirna.hospitalmanagementapi.domain.entities.Patient;
|
||||||
import com.mirna.hospitalmanagementapi.domain.services.PatientService;
|
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;
|
import jakarta.persistence.EntityNotFoundException;
|
||||||
|
|
||||||
@ -38,6 +44,11 @@ public class PatientServiceImpl implements PatientService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private FindPatientsUseCase findPatients;
|
private FindPatientsUseCase findPatients;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserRepository userRepository;
|
||||||
|
@Autowired
|
||||||
|
private BCryptPasswordEncoder passwordEncoder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a new patient to the database.
|
* Adds a new patient to the database.
|
||||||
*
|
*
|
||||||
@ -54,8 +65,7 @@ public class PatientServiceImpl implements PatientService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds a stored patient by id.
|
* Finds a stored patient by id.
|
||||||
*
|
* * @param id A long representing the patient's unique identifier
|
||||||
* @param id A long representing the patient's unique identifier
|
|
||||||
* @return The corresponding patient if successful, or throws an EntityNotFoundException if it is
|
* @return The corresponding patient if successful, or throws an EntityNotFoundException if it is
|
||||||
* non-existent.
|
* non-existent.
|
||||||
* @throws EntityNotFoundException When patient with id provided is non-existent
|
* @throws EntityNotFoundException When patient with id provided is non-existent
|
||||||
@ -73,8 +83,7 @@ public class PatientServiceImpl implements PatientService {
|
|||||||
* Finds patients from the database.
|
* Finds patients from the database.
|
||||||
*
|
*
|
||||||
* @param pageable Pagination information, such as size and page number
|
* @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
|
||||||
* @return A paginated sublist containing data transfer objects with patients public information in the repository
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Page<PatientPublicDataDTO> findPatients(Pageable pageable) {
|
public Page<PatientPublicDataDTO> findPatients(Pageable pageable) {
|
||||||
@ -84,8 +93,7 @@ public class PatientServiceImpl implements PatientService {
|
|||||||
/**
|
/**
|
||||||
* Updates an existing patient record
|
* Updates an existing patient record
|
||||||
* @param patientUpdatedDataDTO Data transfer object containing the patient updated data along with their corresponding id
|
* @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.
|
||||||
* @return The updated patient if successful, or null if there is an error.
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Patient updatePatient(PatientUpdatedDataDTO patientUpdatedDataDTO) {
|
public Patient updatePatient(PatientUpdatedDataDTO patientUpdatedDataDTO) {
|
||||||
@ -141,10 +149,8 @@ public class PatientServiceImpl implements PatientService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Deactivates an existing patient record by provided id
|
* Deactivates an existing patient record by provided id
|
||||||
*
|
* * @param id Long that represents the patient's unique identifier
|
||||||
* @param id Long that represents the patient's unique identifier
|
* * @return The deactivated patient if successful, or throws an
|
||||||
*
|
|
||||||
* @return The deactivated patient if successful, or throws an
|
|
||||||
* EntityNotFoundException if it is non-existent.
|
* EntityNotFoundException if it is non-existent.
|
||||||
* @throws EntityNotFoundException When patient with id provided is non-existent
|
* @throws EntityNotFoundException When patient with id provided is non-existent
|
||||||
*/
|
*/
|
||||||
@ -161,4 +167,45 @@ public class PatientServiceImpl implements PatientService {
|
|||||||
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,23 +2,31 @@ package com.mirna.hospitalmanagementapi.application.services;
|
|||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
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.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import com.mirna.hospitalmanagementapi.application.usecase.user.FindUserByLoginUseCase;
|
import com.mirna.hospitalmanagementapi.application.usecase.user.FindUserByLoginUseCase;
|
||||||
import com.mirna.hospitalmanagementapi.application.usecase.user.SaveUserUseCase;
|
import com.mirna.hospitalmanagementapi.application.usecase.user.SaveUserUseCase;
|
||||||
import com.mirna.hospitalmanagementapi.domain.dtos.auth.UserDTO;
|
import com.mirna.hospitalmanagementapi.domain.dtos.auth.UserDTO;
|
||||||
import com.mirna.hospitalmanagementapi.domain.entities.auth.User;
|
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.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 is an implementation of the UserService interface.
|
||||||
*
|
*
|
||||||
* This class provides methods to perform operations on User entity
|
* This class provides methods to perform operations on User entity
|
||||||
*
|
*
|
||||||
* @author Mirna Gama
|
* @author Mirna Gama (Extended by FlookSP)
|
||||||
* @version 1.0
|
* @version 1.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class UserServiceImpl implements UserService {
|
public class UserServiceImpl implements UserService {
|
||||||
|
|
||||||
@ -28,29 +36,69 @@ public class UserServiceImpl implements UserService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private FindUserByLoginUseCase findUserByLogin;
|
private FindUserByLoginUseCase findUserByLogin;
|
||||||
|
|
||||||
/**
|
@Autowired
|
||||||
* Finds a stored user information by login.
|
private UserRepository userRepository;
|
||||||
*
|
|
||||||
* @param login A string representing the user's system login
|
@Autowired
|
||||||
* @return The corresponding user information if successful, or null if it is non-existent.
|
private PasswordEncoder passwordEncoder;
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public UserDetails findUserByLogin(String login) {
|
public UserDetails findUserByLogin(String login) {
|
||||||
return findUserByLogin.execute(login);
|
return findUserByLogin.execute(login);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
@Override
|
||||||
public User addUser(UserDTO userDTO) {
|
public User addUser(User user) {
|
||||||
|
|
||||||
User user = new User(userDTO);
|
|
||||||
|
|
||||||
return saveUser.execute(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.core.Authentication;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import com.mirna.hospitalmanagementapi.domain.dtos.auth.UserDTO;
|
import com.mirna.hospitalmanagementapi.domain.dtos.auth.UserDTO;
|
||||||
import com.mirna.hospitalmanagementapi.domain.entities.auth.User;
|
import com.mirna.hospitalmanagementapi.domain.entities.auth.User;
|
||||||
import com.mirna.hospitalmanagementapi.domain.services.UserService;
|
import com.mirna.hospitalmanagementapi.domain.services.UserService;
|
||||||
import com.mirna.hospitalmanagementapi.domain.services.auth.AuthService;
|
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.
|
* This class is an implementation of the AuthService interface.
|
||||||
@ -32,10 +50,21 @@ public class AuthServiceImpl implements AuthService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private PasswordEncoder passwordEncoder;
|
private PasswordEncoder passwordEncoder;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PatientRepository patientRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DoctorRepository doctorRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private StaffService staffService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private NurseRepository nurseRepository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs the user login
|
* Performs the user login
|
||||||
*
|
* * @param userDTO Data transfer object containing user credentials for authentication operations
|
||||||
* @param userDTO Data transfer object containing user credentials for authentication operations
|
|
||||||
* @return A fully authentication object including the credentials
|
* @return A fully authentication object including the credentials
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@ -45,20 +74,109 @@ public class AuthServiceImpl implements AuthService {
|
|||||||
|
|
||||||
return manager.authenticate(token);
|
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
|
* Performs the user registration (patients)
|
||||||
*
|
* * @param registrationDTO Data transfer object containing user and patient creation
|
||||||
* @param userDTO Data transfer object containing user credentials for authentication operations
|
|
||||||
* @return A user object including the credentials
|
* @return A user object including the credentials
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public User register(UserDTO userDTO) {
|
@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);
|
||||||
|
|
||||||
String encodedPassword = passwordEncoder.encode(userDTO.password());
|
// 2. สร้างโปรไฟล์ผู้ป่วยและเชื่อมโยงกับ User
|
||||||
userDTO = new UserDTO(userDTO.login(), encodedPassword);
|
Patient patient = new Patient(registrationDTO.patientData(), savedUser);
|
||||||
|
this.patientRepository.save(patient);
|
||||||
|
|
||||||
return this.userService.addUser(userDTO);
|
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,37 +11,23 @@ import com.auth0.jwt.JWT;
|
|||||||
import com.auth0.jwt.algorithms.Algorithm;
|
import com.auth0.jwt.algorithms.Algorithm;
|
||||||
import com.mirna.hospitalmanagementapi.domain.entities.auth.User;
|
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
|
@Component
|
||||||
public class CreateJWTUseCase {
|
public class CreateJWTUseCase {
|
||||||
|
|
||||||
@Value("${api.security.token.secret}")
|
@Value("${api.security.token.secret}")
|
||||||
private String 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) {
|
public String execute(User user) {
|
||||||
Algorithm algorithm = Algorithm.HMAC256(secret);
|
Algorithm algorithm = Algorithm.HMAC256(secret);
|
||||||
|
|
||||||
return JWT.create().withIssuer("Hospital-Management-API")
|
return JWT.create().withIssuer("Hospital-Management-API (Extended Version)")
|
||||||
.withSubject(user.getLogin())
|
.withSubject(user.getLogin())
|
||||||
.withClaim("id", user.getId())
|
.withClaim("id", user.getId())
|
||||||
|
.withClaim("roles", user.getRole().name()) // <-- เพิ่มบรรทัดนี้
|
||||||
.withExpiresAt(_getExpirationDate())
|
.withExpiresAt(_getExpirationDate())
|
||||||
.sign(algorithm);
|
.sign(algorithm);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets an expiration date for the token based on 2 hours duration
|
|
||||||
* @return Instant object containing the expiration date
|
|
||||||
*/
|
|
||||||
private Instant _getExpirationDate() {
|
private Instant _getExpirationDate() {
|
||||||
return LocalDateTime.now().plusHours(2).toInstant(ZoneOffset.of("-03:00"));
|
return LocalDateTime.now().plusHours(2).toInstant(ZoneOffset.of("-03:00"));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,7 +29,7 @@ public class GetJWTSubjectUseCase {
|
|||||||
public String execute(String token) {
|
public String execute(String token) {
|
||||||
Algorithm algorithm = Algorithm.HMAC256(secret);
|
Algorithm algorithm = Algorithm.HMAC256(secret);
|
||||||
DecodedJWT decodedJWT = JWT.require(algorithm)
|
DecodedJWT decodedJWT = JWT.require(algorithm)
|
||||||
.withIssuer("Hospital-Management-API")
|
.withIssuer("Hospital-Management-API (Extended Version)")
|
||||||
.build()
|
.build()
|
||||||
.verify(token);
|
.verify(token);
|
||||||
|
|
||||||
|
|||||||
@ -1,34 +1,22 @@
|
|||||||
package com.mirna.hospitalmanagementapi.application.usecase.consultation;
|
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.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.mirna.hospitalmanagementapi.domain.entities.Consultation;
|
import com.mirna.hospitalmanagementapi.domain.entities.Consultation;
|
||||||
import com.mirna.hospitalmanagementapi.domain.repositories.ConsultationRepository;
|
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
|
@Component
|
||||||
public class FindConsultationByDoctorAndDateUseCase {
|
public class FindConsultationByDoctorAndDateUseCase {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ConsultationRepository consultationRepository;
|
private ConsultationRepository consultationRepository;
|
||||||
|
|
||||||
/**
|
public Consultation execute(Long doctorId, OffsetDateTime consultationDate) {
|
||||||
* Executes the findConsultationByDoctorAndDate method from Consultation repository
|
// เพิ่มบรรทัดนี้เพื่อกำหนดจุดสิ้นสุดของช่วงเวลา
|
||||||
*
|
OffsetDateTime consultationDatePlusOneMinute = consultationDate.plusMinutes(1);
|
||||||
* @param doctorId The doctor's id from the consultation
|
|
||||||
* @param consultationDate The date of the consultation
|
return this.consultationRepository.findConsultationByDoctorAndDate(doctorId, consultationDate, consultationDatePlusOneMinute);
|
||||||
* @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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,34 +1,22 @@
|
|||||||
package com.mirna.hospitalmanagementapi.application.usecase.consultation;
|
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.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.mirna.hospitalmanagementapi.domain.entities.Consultation;
|
import com.mirna.hospitalmanagementapi.domain.entities.Consultation;
|
||||||
import com.mirna.hospitalmanagementapi.domain.repositories.ConsultationRepository;
|
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
|
@Component
|
||||||
public class FindConsultationByPatientAndDateUseCase {
|
public class FindConsultationByPatientAndDateUseCase {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ConsultationRepository consultationRepository;
|
private ConsultationRepository consultationRepository;
|
||||||
|
|
||||||
/**
|
public Consultation execute(Long patientId, OffsetDateTime consultationDate) {
|
||||||
* Executes the findConsultationByPatientAndDate method from Consultation repository
|
// เพิ่มบรรทัดนี้เพื่อกำหนดจุดสิ้นสุดของช่วงเวลา
|
||||||
*
|
OffsetDateTime consultationDatePlusOneMinute = consultationDate.plusMinutes(1);
|
||||||
* @param patientId The patient's id from the consultation
|
|
||||||
* @param consultationDate The date of the consultation
|
return this.consultationRepository.findConsultationByPatientAndDate(patientId, consultationDate, consultationDatePlusOneMinute);
|
||||||
* @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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,6 +1,9 @@
|
|||||||
|
// ไฟล์: FindOneFreeDoctorBySpecialtyUseCase.java
|
||||||
package com.mirna.hospitalmanagementapi.application.usecase.doctor;
|
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.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
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.enums.Specialty;
|
||||||
import com.mirna.hospitalmanagementapi.domain.repositories.DoctorRepository;
|
import com.mirna.hospitalmanagementapi.domain.repositories.DoctorRepository;
|
||||||
|
|
||||||
/**
|
|
||||||
* This class is used to execute the findOneFreeDoctorBySpecialty method
|
|
||||||
*
|
|
||||||
* @author Mirna Gama
|
|
||||||
* @version 1.0
|
|
||||||
*/
|
|
||||||
@Component
|
@Component
|
||||||
public class FindOneFreeDoctorBySpecialtyUseCase {
|
public class FindOneFreeDoctorBySpecialtyUseCase {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private DoctorRepository doctorRepository;
|
private DoctorRepository doctorRepository;
|
||||||
|
|
||||||
/**
|
public Doctor execute(Specialty specialty, OffsetDateTime consultationDate) {
|
||||||
* Executes the findOneFreeDoctorBySpecialty method from Doctor repository
|
// ใช้ Query ใหม่ที่แม่นยำกว่าเดิม
|
||||||
*
|
List<Doctor> freeDoctors = doctorRepository.findFreeDoctorsBySpecialty(specialty, consultationDate);
|
||||||
* @param specialty Desired specialty for doctor search
|
|
||||||
* @param consultationDate Date to check if the doctor is free
|
if (freeDoctors.isEmpty()) {
|
||||||
* @return A random free doctor with the defined specialty if successful, or null if it is non-existent
|
return null;
|
||||||
*
|
}
|
||||||
*/
|
|
||||||
public Doctor execute(Specialty specialty, LocalDateTime consultationDate) {
|
// เลือกแพทย์แบบสุ่มจากรายการที่ว่าง
|
||||||
return doctorRepository.findOneFreeDoctorBySpecialty(specialty, consultationDate);
|
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,
|
String neighborhood,
|
||||||
|
|
||||||
@NotBlank(message="zipCode cannot be blank")
|
@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,
|
String zipCode,
|
||||||
|
|
||||||
@NotBlank(message="city cannot be blank")
|
@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,35 +1,48 @@
|
|||||||
package com.mirna.hospitalmanagementapi.domain.dtos.consultation;
|
package com.mirna.hospitalmanagementapi.domain.dtos.consultation;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.OffsetDateTime;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
|
||||||
import com.mirna.hospitalmanagementapi.domain.enums.Specialty;
|
import com.mirna.hospitalmanagementapi.domain.enums.Specialty;
|
||||||
import com.mirna.hospitalmanagementapi.domain.validators.consultation.constraints.ConsultationDateBusinessHours;
|
import com.mirna.hospitalmanagementapi.domain.validators.consultation.constraints.ConsultationDateBusinessHours;
|
||||||
import com.mirna.hospitalmanagementapi.domain.validators.consultation.constraints.ConsultationDateScheduledInAdvance;
|
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.Future;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data transfer object used to transfer data that will be saved in a Consultation entity
|
* Data transfer object used to transfer data that will be saved in a Consultation entity
|
||||||
*
|
* * @author Mirna Gama (Extended by FlookSP)
|
||||||
* @author Mirna Gama
|
|
||||||
* @version 1.0
|
* @version 1.0
|
||||||
*/
|
*/
|
||||||
public record ConsultationDTO(
|
public record ConsultationDTO(
|
||||||
|
|
||||||
|
@Schema(
|
||||||
|
description = "รหัสแพทย์สำหรับจองโดยตรง (ไม่บังคับ) ต้องเป็น null หากระบุแผนก",
|
||||||
|
example = "1"
|
||||||
|
)
|
||||||
Long doctorId,
|
Long doctorId,
|
||||||
|
|
||||||
|
@Schema(
|
||||||
|
description = "รหัสผู้ป่วยที่ต้องการนัดหมาย",
|
||||||
|
example = "1"
|
||||||
|
)
|
||||||
@NotNull(message="patient id cannot be null")
|
@NotNull(message="patient id cannot be null")
|
||||||
Long patientId,
|
Long patientId,
|
||||||
|
|
||||||
|
@Schema(
|
||||||
|
description = "วันที่และเวลาที่ต้องการนัดหมายในรูปแบบ ISO 8601 พร้อม timezone offset (+07:00 สำหรับประเทศไทย)",
|
||||||
|
example = "2025-09-15T10:00:00+07:00"
|
||||||
|
)
|
||||||
@NotNull(message="consultation date cannot be null")
|
@NotNull(message="consultation date cannot be null")
|
||||||
@Future
|
@Future
|
||||||
@JsonFormat(pattern = "dd/MM/yyyy HH:mm")
|
|
||||||
@ConsultationDateScheduledInAdvance
|
@ConsultationDateScheduledInAdvance
|
||||||
@ConsultationDateBusinessHours
|
@ConsultationDateBusinessHours
|
||||||
LocalDateTime consultationDate,
|
OffsetDateTime consultationDate,
|
||||||
|
|
||||||
|
@Schema(
|
||||||
|
description = "แผนกที่ต้องการ (ไม่บังคับ) ต้องระบุหากไม่ได้ระบุรหัสแพทย์",
|
||||||
|
example = "ORTHOPEDICS"
|
||||||
|
)
|
||||||
Specialty specialty
|
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;
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package com.mirna.hospitalmanagementapi.domain.dtos.inventory;
|
||||||
|
|
||||||
|
import com.mirna.hospitalmanagementapi.domain.entities.inventory.InventorySupplier;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class SupplierResponseDTO {
|
||||||
|
|
||||||
|
private UUID id;
|
||||||
|
private String supplierName;
|
||||||
|
|
||||||
|
public SupplierResponseDTO(InventorySupplier entity) {
|
||||||
|
this.id = entity.getId();
|
||||||
|
this.supplierName = entity.getSupplierName();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getters
|
||||||
|
public UUID getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSupplierName() {
|
||||||
|
return supplierName;
|
||||||
|
}
|
||||||
|
}
|
||||||
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