[update] Enhance project configuration and patient data handling. Add Google Drive API dependencies and update .gitignore to exclude JSON files. Improve CheckUpPage and QueueViewPage for better date handling and patient information extraction. Update medical invoice details for accuracy.

This commit is contained in:
Lê Thành Đạt committed 2025-07-22 02:52:36 +07:00
1 parent c5515591c3
commit 69751b4417
12 files changed
+949 -14

No files matched your search

+10
View File
@@ -127,6 +127,8 @@ buildNumber.properties
.mvn/timing.properties
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
.mvn/wrapper/maven-wrapper.jar
# ignore all json
*.json
# User-generated content
img_db/
@@ -149,3 +151,11 @@ src/main/resources/image/checkup_media/34/VID_34_20250604_120241.mp4
src/main/resources/image/checkup_media/8/IMG_8_20250604_112523.png
src/main/resources/image/checkup_media/8/IMG_8_20250604_112526.png
src/main/resources/image/checkup_media/8/VID_8_20250604_115008.mp4
src/main/resources/client_secret_1063629801433-01ubsp30l0sabhbk28q2esh9c3bhjgka.apps.googleusercontent.com.json
GOOGLE_DRIVE_SETUP.md
src/main/resources/google-drive-service-account.json
tokens/StoredCredential
src/main/resources/database/BSK.db
src/main/resources/database/BSK.db
src/main/resources/database/BSK.db
+14
View File
@@ -1,6 +1,20 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "GoogleDriveOAuthTest",
"request": "launch",
"mainClass": "BsK.server.test.GoogleDriveOAuthTest",
"projectName": "ldS_BsK"
},
{
"type": "java",
"name": "GoogleDriveTest",
"request": "launch",
"mainClass": "BsK.server.test.GoogleDriveTest",
"projectName": "ldS_BsK"
},
{
"type": "java",
"name": "DateUtils",
Binary file not shown.
+33
View File
@@ -273,6 +273,39 @@
<artifactId>jasperreports-pdf</artifactId>
<version>7.0.3</version>
</dependency>
<!-- Google Drive API -->
<dependency>
<groupId>com.google.apis</groupId>
<artifactId>google-api-services-drive</artifactId>
<version>v3-rev20240914-2.0.0</version>
</dependency>
<!-- Google Auth Library -->
<dependency>
<groupId>com.google.auth</groupId>
<artifactId>google-auth-library-oauth2-http</artifactId>
<version>1.27.0</version>
</dependency>
<!-- Google OAuth2 Client -->
<dependency>
<groupId>com.google.oauth-client</groupId>
<artifactId>google-oauth-client-jetty</artifactId>
<version>1.36.0</version>
</dependency>
<!-- QR Code Generator -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.5.3</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.5.3</version>
</dependency>
</dependencies>
</project>
@@ -1905,7 +1905,11 @@ public class CheckUpPage extends JPanel {
suggestionField.setText(selectedPatient.getSuggestion()); // De nghi
diagnosisField.setText(selectedPatient.getDiagnosis()); // Chuan doan
conclusionField.setText(selectedPatient.getConclusion()); // Ket luan
recheckupDatePicker.getJFormattedTextField().setText(DateUtils.convertToDisplayFormat(selectedPatient.getReCheckupDate())); // Ngày khám lại
if (selectedPatient.getReCheckupDate() != null) {
recheckupDatePicker.getJFormattedTextField().setText(DateUtils.convertToDisplayFormat(selectedPatient.getReCheckupDate()));
} else {
recheckupDatePicker.getJFormattedTextField().setText("");
}
// Handle RTF notes content
String notes = selectedPatient.getNotes();
@@ -1,6 +1,7 @@
package BsK.client.ui.component.QueueViewPage;
import BsK.client.LocalStorage;
import BsK.common.util.date.DateUtils;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
@@ -288,26 +289,32 @@ public class QueueViewPage extends JFrame {
SimpleDateFormat inputDateFormat = new SimpleDateFormat("dd/MM/yyyy");
for (String[] row : fullQueueData) {
if (row.length > 3) {
if (row.length > 15) { // Changed from > 3 to > 15 to ensure we have DOB data
String maKhamBenh = row[0];
String ho = row[2];
String ten = row[3];
String hoVaTen = ho + " " + ten;
String dateStr = row[1];
String customerDob = row[15]; // Use customer DOB instead of checkup date
String namSinh = "N/A";
try {
Date parsedDate;
if (dateStr.matches("\\d+")) {
parsedDate = new Date(Long.parseLong(dateStr));
} else {
parsedDate = inputDateFormat.parse(dateStr);
if (customerDob != null && !customerDob.isEmpty()) {
// Extract year from DOB using DateUtils for consistency
int year = DateUtils.extractYearFromTimestamp(customerDob);
if (year != -1) {
namSinh = String.valueOf(year);
} else {
// Fallback: try to parse as date string and extract year
try {
Date dobDate = DateUtils.convertToDate(customerDob);
if (dobDate != null) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(dobDate);
namSinh = String.valueOf(calendar.get(Calendar.YEAR));
}
} catch (Exception e) {
System.err.println("Lỗi phân tích ngày sinh cho năm trên màn hình chờ TV: " + customerDob + " - " + e.getMessage());
}
}
Calendar calendar = Calendar.getInstance();
calendar.setTime(parsedDate);
namSinh = String.valueOf(calendar.get(Calendar.YEAR));
} catch (ParseException | NumberFormatException e) {
System.err.println("Lỗi phân tích ngày cho năm trên màn hình chờ TV: " + dateStr + " - " + e.getMessage());
}
tvDataList.add(new Object[]{maKhamBenh, hoVaTen, namSinh});
}
@@ -0,0 +1,243 @@
package BsK.server.service;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.FileContent;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.DriveScopes;
import com.google.api.services.drive.model.File;
import com.google.api.services.drive.model.FileList;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.auth.oauth2.ServiceAccountCredentials;
import lombok.extern.slf4j.Slf4j;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
@Slf4j
public class GoogleDriveService {
private static final String APPLICATION_NAME = "BSK Clinic Management System";
private static final JsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance();
private static final List<String> SCOPES = Collections.singletonList(DriveScopes.DRIVE_FILE);
// Path to service account key file (will be configured)
private static final String SERVICE_ACCOUNT_KEY_PATH = "src/main/resources/google-drive-service-account.json";
private Drive driveService;
private String rootFolderId; // BSK Clinic root folder
public GoogleDriveService() {
try {
this.driveService = buildDriveService();
this.rootFolderId = getOrCreateRootFolder();
log.info("Google Drive service initialized successfully");
} catch (Exception e) {
log.error("Failed to initialize Google Drive service", e);
throw new RuntimeException("Google Drive service initialization failed", e);
}
}
private Drive buildDriveService() throws GeneralSecurityException, IOException {
GoogleCredentials credentials = ServiceAccountCredentials
.fromStream(new FileInputStream(SERVICE_ACCOUNT_KEY_PATH))
.createScoped(SCOPES);
return new Drive.Builder(
GoogleNetHttpTransport.newTrustedTransport(),
JSON_FACTORY,
new HttpCredentialsAdapter(credentials))
.setApplicationName(APPLICATION_NAME)
.build();
}
/**
* Get or create the root folder for BSK Clinic
*/
private String getOrCreateRootFolder() throws IOException {
String folderName = "BSK_Clinic_Patient_Files";
// Search for existing root folder
String query = "name='" + folderName + "' and mimeType='application/vnd.google-apps.folder' and trashed=false";
FileList result = driveService.files().list()
.setQ(query)
.setSpaces("drive")
.execute();
List<File> files = result.getFiles();
if (files != null && !files.isEmpty()) {
String folderId = files.get(0).getId();
log.info("Found existing root folder: {} (ID: {})", folderName, folderId);
return folderId;
}
// Create root folder if it doesn't exist
File folderMetadata = new File();
folderMetadata.setName(folderName);
folderMetadata.setMimeType("application/vnd.google-apps.folder");
File folder = driveService.files().create(folderMetadata)
.setFields("id")
.execute();
log.info("Created new root folder: {} (ID: {})", folderName, folder.getId());
return folder.getId();
}
/**
* Create a folder for a specific patient
*/
public String createPatientFolder(String patientId, String patientName) throws IOException {
String folderName = "Patient_" + patientId + "_" + sanitizeFileName(patientName);
// Check if folder already exists
Optional<String> existingFolderId = findPatientFolder(patientId);
if (existingFolderId.isPresent()) {
log.info("Patient folder already exists: {} (ID: {})", folderName, existingFolderId.get());
return existingFolderId.get();
}
// Create new patient folder
File folderMetadata = new File();
folderMetadata.setName(folderName);
folderMetadata.setMimeType("application/vnd.google-apps.folder");
folderMetadata.setParents(Collections.singletonList(rootFolderId));
File folder = driveService.files().create(folderMetadata)
.setFields("id")
.execute();
log.info("Created patient folder: {} (ID: {})", folderName, folder.getId());
return folder.getId();
}
/**
* Find existing patient folder by patient ID
*/
private Optional<String> findPatientFolder(String patientId) throws IOException {
String query = "name contains 'Patient_" + patientId + "_' and mimeType='application/vnd.google-apps.folder' and trashed=false and '" + rootFolderId + "' in parents";
FileList result = driveService.files().list()
.setQ(query)
.setSpaces("drive")
.execute();
List<File> files = result.getFiles();
if (files != null && !files.isEmpty()) {
return Optional.of(files.get(0).getId());
}
return Optional.empty();
}
/**
* Upload a file to a patient's folder
*/
public String uploadFile(String patientFolderId, java.io.File localFile, String fileName) throws IOException {
String mimeType = determineMimeType(fileName);
File fileMetadata = new File();
fileMetadata.setName(fileName);
fileMetadata.setParents(Collections.singletonList(patientFolderId));
FileContent mediaContent = new FileContent(mimeType, localFile);
File uploadedFile = driveService.files().create(fileMetadata, mediaContent)
.setFields("id,webViewLink,webContentLink")
.execute();
log.info("Uploaded file: {} (ID: {})", fileName, uploadedFile.getId());
return uploadedFile.getId();
}
/**
* Get the public sharing URL for a folder
*/
public String getFolderSharingUrl(String folderId) throws IOException {
// Make the folder publicly viewable
com.google.api.services.drive.model.Permission permission = new com.google.api.services.drive.model.Permission();
permission.setType("anyone");
permission.setRole("reader");
driveService.permissions().create(folderId, permission).execute();
// Get the folder details with web view link
File folder = driveService.files().get(folderId)
.setFields("webViewLink")
.execute();
return folder.getWebViewLink();
}
/**
* Create a test folder and upload sample files
*/
public void runConnectionTest() throws IOException {
log.info("Starting Google Drive connection test...");
// Create test folder
String testFolderId = createPatientFolder("TEST001", "Test Patient");
// Create a test text file
java.io.File testFile = new java.io.File("test-connection.txt");
try {
java.io.FileWriter writer = new java.io.FileWriter(testFile);
writer.write("BSK Clinic - Google Drive Connection Test\n");
writer.write("Timestamp: " + java.time.LocalDateTime.now() + "\n");
writer.write("This file verifies that the Google Drive integration is working correctly.\n");
writer.close();
// Upload the test file
String fileId = uploadFile(testFolderId, testFile, "connection-test.txt");
// Get sharing URL
String folderUrl = getFolderSharingUrl(testFolderId);
log.info("✅ Google Drive connection test successful!");
log.info("📁 Test folder URL: {}", folderUrl);
log.info("📄 Test file ID: {}", fileId);
// Clean up test file
testFile.delete();
} catch (Exception e) {
log.error("❌ Google Drive connection test failed", e);
if (testFile.exists()) {
testFile.delete();
}
throw e;
}
}
private String sanitizeFileName(String fileName) {
// Remove or replace invalid characters for file names
return fileName.replaceAll("[^a-zA-Z0-9._-]", "_");
}
private String determineMimeType(String fileName) {
String lowerFileName = fileName.toLowerCase();
if (lowerFileName.endsWith(".pdf")) {
return "application/pdf";
} else if (lowerFileName.endsWith(".jpg") || lowerFileName.endsWith(".jpeg")) {
return "image/jpeg";
} else if (lowerFileName.endsWith(".png")) {
return "image/png";
} else if (lowerFileName.endsWith(".txt")) {
return "text/plain";
} else if (lowerFileName.endsWith(".doc")) {
return "application/msword";
} else if (lowerFileName.endsWith(".docx")) {
return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
}
return "application/octet-stream"; // Default binary
}
public String getRootFolderId() {
return rootFolderId;
}
}
@@ -0,0 +1,266 @@
package BsK.server.service;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.FileContent;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.client.util.store.FileDataStoreFactory;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.DriveScopes;
import com.google.api.services.drive.model.File;
import com.google.api.services.drive.model.FileList;
import lombok.extern.slf4j.Slf4j;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.GeneralSecurityException;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
@Slf4j
public class GoogleDriveServiceOAuth {
private static final String APPLICATION_NAME = "BSK Clinic Management System";
private static final JsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance();
private static final List<String> SCOPES = Collections.singletonList(DriveScopes.DRIVE_FILE);
// Path to OAuth2 client credentials file
private static final String OAUTH_CREDENTIALS_PATH = "src/main/resources/google-oauth-credentials.json";
// Directory to store authorization tokens
private static final String TOKENS_DIRECTORY_PATH = "tokens";
private Drive driveService;
private String rootFolderId; // BSK Clinic root folder
public GoogleDriveServiceOAuth() {
try {
this.driveService = buildDriveService();
this.rootFolderId = getOrCreateRootFolder();
log.info("Google Drive OAuth service initialized successfully");
} catch (Exception e) {
log.error("Failed to initialize Google Drive OAuth service", e);
throw new RuntimeException("Google Drive OAuth service initialization failed", e);
}
}
private Drive buildDriveService() throws GeneralSecurityException, IOException {
// Load client secrets
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(
JSON_FACTORY,
new InputStreamReader(new FileInputStream(OAUTH_CREDENTIALS_PATH))
);
// Build flow and trigger user authorization request
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
GoogleNetHttpTransport.newTrustedTransport(),
JSON_FACTORY,
clientSecrets,
SCOPES)
.setDataStoreFactory(new FileDataStoreFactory(new java.io.File(TOKENS_DIRECTORY_PATH)))
.setAccessType("offline")
.build();
LocalServerReceiver receiver = new LocalServerReceiver.Builder().setPort(8888).build();
Credential credential = new AuthorizationCodeInstalledApp(flow, receiver).authorize("user");
// Build a new authorized API client service
return new Drive.Builder(
GoogleNetHttpTransport.newTrustedTransport(),
JSON_FACTORY,
credential)
.setApplicationName(APPLICATION_NAME)
.build();
}
/**
* Get or create the root folder for BSK Clinic
*/
private String getOrCreateRootFolder() throws IOException {
String folderName = "BSK_Clinic_Patient_Files";
// Search for existing root folder
String query = "name='" + folderName + "' and mimeType='application/vnd.google-apps.folder' and trashed=false";
FileList result = driveService.files().list()
.setQ(query)
.setSpaces("drive")
.execute();
List<File> files = result.getFiles();
if (files != null && !files.isEmpty()) {
String folderId = files.get(0).getId();
log.info("Found existing root folder: {} (ID: {})", folderName, folderId);
return folderId;
}
// Create root folder if it doesn't exist
File folderMetadata = new File();
folderMetadata.setName(folderName);
folderMetadata.setMimeType("application/vnd.google-apps.folder");
File folder = driveService.files().create(folderMetadata)
.setFields("id")
.execute();
log.info("Created new root folder: {} (ID: {})", folderName, folder.getId());
return folder.getId();
}
/**
* Create a folder for a specific patient
*/
public String createPatientFolder(String patientId, String patientName) throws IOException {
String folderName = "Patient_" + patientId + "_" + sanitizeFileName(patientName);
// Check if folder already exists
Optional<String> existingFolderId = findPatientFolder(patientId);
if (existingFolderId.isPresent()) {
log.info("Patient folder already exists: {} (ID: {})", folderName, existingFolderId.get());
return existingFolderId.get();
}
// Create new patient folder
File folderMetadata = new File();
folderMetadata.setName(folderName);
folderMetadata.setMimeType("application/vnd.google-apps.folder");
folderMetadata.setParents(Collections.singletonList(rootFolderId));
File folder = driveService.files().create(folderMetadata)
.setFields("id")
.execute();
log.info("Created patient folder: {} (ID: {})", folderName, folder.getId());
return folder.getId();
}
/**
* Find existing patient folder by patient ID
*/
private Optional<String> findPatientFolder(String patientId) throws IOException {
String query = "name contains 'Patient_" + patientId + "_' and mimeType='application/vnd.google-apps.folder' and trashed=false and '" + rootFolderId + "' in parents";
FileList result = driveService.files().list()
.setQ(query)
.setSpaces("drive")
.execute();
List<File> files = result.getFiles();
if (files != null && !files.isEmpty()) {
return Optional.of(files.get(0).getId());
}
return Optional.empty();
}
/**
* Upload a file to a patient's folder
*/
public String uploadFile(String patientFolderId, java.io.File localFile, String fileName) throws IOException {
String mimeType = determineMimeType(fileName);
File fileMetadata = new File();
fileMetadata.setName(fileName);
fileMetadata.setParents(Collections.singletonList(patientFolderId));
FileContent mediaContent = new FileContent(mimeType, localFile);
File uploadedFile = driveService.files().create(fileMetadata, mediaContent)
.setFields("id,webViewLink,webContentLink")
.execute();
log.info("Uploaded file: {} (ID: {})", fileName, uploadedFile.getId());
return uploadedFile.getId();
}
/**
* Get the public sharing URL for a folder
*/
public String getFolderSharingUrl(String folderId) throws IOException {
// Make the folder publicly viewable
com.google.api.services.drive.model.Permission permission = new com.google.api.services.drive.model.Permission();
permission.setType("anyone");
permission.setRole("reader");
driveService.permissions().create(folderId, permission).execute();
// Get the folder details with web view link
File folder = driveService.files().get(folderId)
.setFields("webViewLink")
.execute();
return folder.getWebViewLink();
}
/**
* Create a test folder and upload sample files
*/
public void runConnectionTest() throws IOException {
log.info("Starting Google Drive OAuth connection test...");
// Create test folder
String testFolderId = createPatientFolder("TEST002", "OAuth Test Patient");
// Create a test text file
java.io.File testFile = new java.io.File("test-oauth-connection.txt");
try {
java.io.FileWriter writer = new java.io.FileWriter(testFile);
writer.write("BSK Clinic - Google Drive OAuth Connection Test\n");
writer.write("Timestamp: " + java.time.LocalDateTime.now() + "\n");
writer.write("This file verifies that the Google Drive OAuth integration is working correctly.\n");
writer.write("Authentication method: OAuth2 with user consent\n");
writer.close();
// Upload the test file
String fileId = uploadFile(testFolderId, testFile, "oauth-connection-test.txt");
// Get sharing URL
String folderUrl = getFolderSharingUrl(testFolderId);
log.info("✅ Google Drive OAuth connection test successful!");
log.info("📁 Test folder URL: {}", folderUrl);
log.info("📄 Test file ID: {}", fileId);
// Clean up test file
testFile.delete();
} catch (Exception e) {
log.error("❌ Google Drive OAuth connection test failed", e);
if (testFile.exists()) {
testFile.delete();
}
throw e;
}
}
private String sanitizeFileName(String fileName) {
// Remove or replace invalid characters for file names
return fileName.replaceAll("[^a-zA-Z0-9._-]", "_");
}
private String determineMimeType(String fileName) {
String lowerFileName = fileName.toLowerCase();
if (lowerFileName.endsWith(".pdf")) {
return "application/pdf";
} else if (lowerFileName.endsWith(".jpg") || lowerFileName.endsWith(".jpeg")) {
return "image/jpeg";
} else if (lowerFileName.endsWith(".png")) {
return "image/png";
} else if (lowerFileName.endsWith(".txt")) {
return "text/plain";
} else if (lowerFileName.endsWith(".doc")) {
return "application/msword";
} else if (lowerFileName.endsWith(".docx")) {
return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
}
return "application/octet-stream"; // Default binary
}
public String getRootFolderId() {
return rootFolderId;
}
}
@@ -0,0 +1,125 @@
package BsK.server.test;
import BsK.server.service.GoogleDriveServiceOAuth;
import BsK.server.util.QRCodeGenerator;
import lombok.extern.slf4j.Slf4j;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
@Slf4j
public class GoogleDriveOAuthTest {
public static void main(String[] args) {
log.info("🚀 Starting BSK Google Drive OAuth Integration Test");
try {
// Initialize Google Drive OAuth service
log.info("🔐 This will open a browser window for Google authentication...");
GoogleDriveServiceOAuth driveService = new GoogleDriveServiceOAuth();
// Run basic connection test
driveService.runConnectionTest();
// Test patient folder creation and file upload
testPatientFileOperations(driveService);
// Test QR code generation
testQRCodeGeneration();
log.info("🎉 All Google Drive OAuth tests completed successfully!");
} catch (Exception e) {
log.error("❌ Google Drive OAuth test failed", e);
System.exit(1);
}
}
private static void testPatientFileOperations(GoogleDriveServiceOAuth driveService) throws IOException {
log.info("🧪 Testing patient file operations...");
// Test patient folder creation
String patientId = "P002";
String patientName = "Trần Thị B";
String patientFolderId = driveService.createPatientFolder(patientId, patientName);
// Create sample PDF file (mock)
File testPdf = createSamplePDF("medical_report_" + patientId + ".pdf");
// Create sample image file (mock)
File testImage = createSampleTextFile("xray_" + patientId + ".txt", "Sample X-ray data for patient " + patientId);
try {
// Upload files
String pdfFileId = driveService.uploadFile(patientFolderId, testPdf, testPdf.getName());
String imageFileId = driveService.uploadFile(patientFolderId, testImage, "xray_" + patientId + ".jpg");
// Get folder sharing URL
String folderUrl = driveService.getFolderSharingUrl(patientFolderId);
log.info("✅ Patient folder created successfully");
log.info("📁 Patient folder URL: {}", folderUrl);
log.info("📄 PDF file ID: {}", pdfFileId);
log.info("🖼️ Image file ID: {}", imageFileId);
// Test QR code generation for this folder
testQRCodeForFolder(folderUrl, patientId);
} finally {
// Clean up test files
if (testPdf.exists()) testPdf.delete();
if (testImage.exists()) testImage.delete();
}
}
private static void testQRCodeGeneration() {
log.info("🧪 Testing QR code generation...");
QRCodeGenerator.testQRGeneration();
}
private static void testQRCodeForFolder(String folderUrl, String patientId) {
try {
log.info("🧪 Testing QR code generation for patient folder...");
String qrFileName = "patient_" + patientId + "_qr.png";
File qrFile = QRCodeGenerator.generateQRCode(folderUrl, qrFileName);
log.info("✅ QR code generated for patient folder: {}", qrFile.getAbsolutePath());
log.info("📱 QR code contains URL: {}", folderUrl);
// Clean up
if (qrFile.exists()) {
qrFile.delete();
log.info("🧹 QR code file cleaned up");
}
} catch (Exception e) {
log.error("❌ QR code generation failed for patient folder", e);
}
}
private static File createSamplePDF(String fileName) throws IOException {
File file = new File(fileName);
FileWriter writer = new FileWriter(file);
writer.write("BSK Clinic - Sample Medical Report (OAuth Test)\n");
writer.write("==========================================\n\n");
writer.write("Patient ID: P002\n");
writer.write("Patient Name: Trần Thị B\n");
writer.write("Date: " + java.time.LocalDate.now() + "\n\n");
writer.write("This is a sample medical report for testing Google Drive OAuth integration.\n");
writer.write("In production, this would be a properly formatted PDF report.\n");
writer.write("Authentication method: OAuth2 with user consent\n");
writer.close();
return file;
}
private static File createSampleTextFile(String fileName, String content) throws IOException {
File file = new File(fileName);
FileWriter writer = new FileWriter(file);
writer.write(content);
writer.write("\nCreated: " + java.time.LocalDateTime.now());
writer.write("\nAuthentication method: OAuth2 with user consent");
writer.close();
return file;
}
}
@@ -0,0 +1,122 @@
package BsK.server.test;
import BsK.server.service.GoogleDriveService;
import BsK.server.util.QRCodeGenerator;
import lombok.extern.slf4j.Slf4j;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
@Slf4j
public class GoogleDriveTest {
public static void main(String[] args) {
log.info("🚀 Starting BSK Google Drive Integration Test");
try {
// Initialize Google Drive service
GoogleDriveService driveService = new GoogleDriveService();
// Run basic connection test
driveService.runConnectionTest();
// Test patient folder creation and file upload
testPatientFileOperations(driveService);
// Test QR code generation
testQRCodeGeneration();
log.info("🎉 All Google Drive tests completed successfully!");
} catch (Exception e) {
log.error("❌ Google Drive test failed", e);
System.exit(1);
}
}
private static void testPatientFileOperations(GoogleDriveService driveService) throws IOException {
log.info("🧪 Testing patient file operations...");
// Test patient folder creation
String patientId = "P001";
String patientName = "Nguyễn Văn A";
String patientFolderId = driveService.createPatientFolder(patientId, patientName);
// Create sample PDF file (mock)
File testPdf = createSamplePDF("sample_report_" + patientId + ".pdf");
// Create sample image file (mock)
File testImage = createSampleTextFile("ultrasound_" + patientId + ".txt", "Sample ultrasound data for patient " + patientId);
try {
// Upload files
String pdfFileId = driveService.uploadFile(patientFolderId, testPdf, testPdf.getName());
String imageFileId = driveService.uploadFile(patientFolderId, testImage, "ultrasound_" + patientId + ".jpg");
// Get folder sharing URL
String folderUrl = driveService.getFolderSharingUrl(patientFolderId);
log.info("✅ Patient folder created successfully");
log.info("📁 Patient folder URL: {}", folderUrl);
log.info("📄 PDF file ID: {}", pdfFileId);
log.info("🖼️ Image file ID: {}", imageFileId);
// Test QR code generation for this folder
testQRCodeForFolder(folderUrl, patientId);
} finally {
// Clean up test files
if (testPdf.exists()) testPdf.delete();
if (testImage.exists()) testImage.delete();
}
}
private static void testQRCodeGeneration() {
log.info("🧪 Testing QR code generation...");
QRCodeGenerator.testQRGeneration();
}
private static void testQRCodeForFolder(String folderUrl, String patientId) {
try {
log.info("🧪 Testing QR code generation for patient folder...");
String qrFileName = "patient_" + patientId + "_qr.png";
File qrFile = QRCodeGenerator.generateQRCode(folderUrl, qrFileName);
log.info("✅ QR code generated for patient folder: {}", qrFile.getAbsolutePath());
log.info("📱 QR code contains URL: {}", folderUrl);
// Clean up
if (qrFile.exists()) {
qrFile.delete();
log.info("🧹 QR code file cleaned up");
}
} catch (Exception e) {
log.error("❌ QR code generation failed for patient folder", e);
}
}
private static File createSamplePDF(String fileName) throws IOException {
File file = new File(fileName);
FileWriter writer = new FileWriter(file);
writer.write("BSK Clinic - Sample Medical Report\n");
writer.write("=================================\n\n");
writer.write("Patient ID: P001\n");
writer.write("Patient Name: Nguyễn Văn A\n");
writer.write("Date: " + java.time.LocalDate.now() + "\n\n");
writer.write("This is a sample medical report for testing Google Drive integration.\n");
writer.write("In production, this would be a properly formatted PDF report.\n");
writer.close();
return file;
}
private static File createSampleTextFile(String fileName, String content) throws IOException {
File file = new File(fileName);
FileWriter writer = new FileWriter(file);
writer.write(content);
writer.write("\nCreated: " + java.time.LocalDateTime.now());
writer.close();
return file;
}
}
@@ -0,0 +1,111 @@
package BsK.server.util;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import lombok.extern.slf4j.Slf4j;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
@Slf4j
public class QRCodeGenerator {
private static final int DEFAULT_WIDTH = 200;
private static final int DEFAULT_HEIGHT = 200;
private static final int BLACK = 0xFF000000;
private static final int WHITE = 0xFFFFFFFF;
/**
* Generate QR code for a given URL and save as image file
*/
public static File generateQRCode(String url, String fileName) throws WriterException, IOException {
return generateQRCode(url, fileName, DEFAULT_WIDTH, DEFAULT_HEIGHT);
}
/**
* Generate QR code with custom dimensions
*/
public static File generateQRCode(String url, String fileName, int width, int height) throws WriterException, IOException {
QRCodeWriter qrCodeWriter = new QRCodeWriter();
BitMatrix bitMatrix = qrCodeWriter.encode(url, BarcodeFormat.QR_CODE, width, height);
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
bufferedImage.setRGB(x, y, bitMatrix.get(x, y) ? BLACK : WHITE);
}
}
File qrCodeFile = new File(fileName);
ImageIO.write(bufferedImage, "PNG", qrCodeFile);
log.info("QR code generated: {} for URL: {}", fileName, url);
return qrCodeFile;
}
/**
* Generate QR code as BufferedImage (for embedding in reports)
*/
public static BufferedImage generateQRCodeImage(String url, int width, int height) throws WriterException {
QRCodeWriter qrCodeWriter = new QRCodeWriter();
BitMatrix bitMatrix = qrCodeWriter.encode(url, BarcodeFormat.QR_CODE, width, height);
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
bufferedImage.setRGB(x, y, bitMatrix.get(x, y) ? BLACK : WHITE);
}
}
return bufferedImage;
}
/**
* Generate QR code with custom colors
*/
public static BufferedImage generateQRCodeImage(String url, int width, int height, Color foregroundColor, Color backgroundColor) throws WriterException {
QRCodeWriter qrCodeWriter = new QRCodeWriter();
BitMatrix bitMatrix = qrCodeWriter.encode(url, BarcodeFormat.QR_CODE, width, height);
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
int foregroundRGB = foregroundColor.getRGB();
int backgroundRGB = backgroundColor.getRGB();
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
bufferedImage.setRGB(x, y, bitMatrix.get(x, y) ? foregroundRGB : backgroundRGB);
}
}
return bufferedImage;
}
/**
* Test method to generate a sample QR code
*/
public static void testQRGeneration() {
try {
String testUrl = "https://drive.google.com/drive/folders/test123";
String fileName = "test-qr-code.png";
File qrFile = generateQRCode(testUrl, fileName);
log.info("✅ Test QR code generated successfully: {}", qrFile.getAbsolutePath());
// Clean up test file
if (qrFile.exists()) {
qrFile.delete();
log.info("🧹 Test QR code file cleaned up");
}
} catch (Exception e) {
log.error("❌ QR code generation test failed", e);
}
}
}
Binary file not shown.