From b1c7e65bab47befdb858962ba79851d571332102 Mon Sep 17 00:00:00 2001
From: muoimeo <bvnminh6a01@gmail.com>
Date: Thu, 10 Apr 2025 13:45:20 +0700
Subject: [PATCH] fix fix fix

---
 app/models/measurement.py         |  14 ++-
 app/models/patient.py             |  11 +-
 app/models/procedure.py           |   1 +
 app/models/referral.py            |   1 +
 app/models/report.py              |   1 +
 app/routes/patients.py            |   8 +-
 app/routes/report.py              |   4 +-
 app/templates/patient_detail.html |   4 +-
 app/templates/upload.html         |   2 +-
 init_database.py                  | 171 +++++++++++++++++++++++++++++-
 requirements.txt                  |  25 ++++-
 11 files changed, 226 insertions(+), 16 deletions(-)

diff --git a/app/models/measurement.py b/app/models/measurement.py
index b9f17cb..b5bb5f0 100644
--- a/app/models/measurement.py
+++ b/app/models/measurement.py
@@ -7,9 +7,10 @@ class PhysiologicalMeasurement(db.Model):
     
     id = db.Column('measurementID', db.Integer, primary_key=True)
     encounter_id = db.Column('encounterId', db.Integer, db.ForeignKey('encounters.encounterId'), nullable=False)
+    patient_id = db.Column('patientID', db.String(20), db.ForeignKey('patients.patientID'), nullable=False)
     
     # Các trường từ schema MySQL
-    measurementDateTime = db.Column(db.DateTime)
+    measurementDateTime = db.Column(db.DateTime, default=datetime.utcnow)
     end_tidal_co2 = db.Column(db.Float)
     feed_vol = db.Column(db.Float)
     feed_vol_adm = db.Column(db.Float)
@@ -26,5 +27,16 @@ class PhysiologicalMeasurement(db.Model):
     tidal_vol_kg = db.Column(db.Float)
     tidal_vol_spon = db.Column(db.Float)
     
+    # Trường bổ sung cho mẫu mới
+    temperature = db.Column(db.Float)
+    heart_rate = db.Column(db.Integer)
+    respiratory_rate = db.Column(db.Integer)
+    blood_pressure_systolic = db.Column(db.Integer)
+    blood_pressure_diastolic = db.Column(db.Integer)
+    oxygen_saturation = db.Column(db.Float)
+    bmi = db.Column(db.Float)
+    tidal_volume = db.Column(db.Float)
+    notes = db.Column(db.Text)
+    
     def __repr__(self):
         return f'<PhysiologicalMeasurement {self.id} for Encounter {self.encounter_id}>' 
\ No newline at end of file
diff --git a/app/models/patient.py b/app/models/patient.py
index 90a1b69..60a06ef 100644
--- a/app/models/patient.py
+++ b/app/models/patient.py
@@ -6,7 +6,7 @@ class Patient(db.Model):
     """Patient model containing basic patient information"""
     __tablename__ = 'patients'
     
-    id = db.Column('patientID', db.Integer, primary_key=True)
+    id = db.Column('patientID', db.String(20), primary_key=True)
     firstName = db.Column(db.String(50))
     lastName = db.Column(db.String(50))
     age = db.Column(db.Integer)
@@ -54,7 +54,7 @@ class Encounter(db.Model):
     __tablename__ = 'encounters'
     
     id = db.Column('encounterId', db.Integer, primary_key=True)
-    patient_id = db.Column('patientID', db.Integer, db.ForeignKey('patients.patientID'), nullable=False)
+    patient_id = db.Column('patientID', db.String(20), db.ForeignKey('patients.patientID'), nullable=False)
     
     # Encounter details
     admissionDateTime = db.Column(db.DateTime, nullable=False)
@@ -73,4 +73,9 @@ class Encounter(db.Model):
     updatedAt = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
     
     def __repr__(self):
-        return f'<Encounter {self.id}>' 
\ No newline at end of file
+        return f'<Encounter {self.id}>'
+    
+    @property
+    def admission_date(self):
+        """Thuộc tính ảo để tương thích với code cũ. Trả về giá trị của admissionDateTime"""
+        return self.admissionDateTime 
\ No newline at end of file
diff --git a/app/models/procedure.py b/app/models/procedure.py
index cd60c87..5ffe1b7 100644
--- a/app/models/procedure.py
+++ b/app/models/procedure.py
@@ -7,6 +7,7 @@ class Procedure(db.Model):
     
     id = db.Column('procedureID', db.Integer, primary_key=True)
     encounter_id = db.Column('encounterId', db.Integer, db.ForeignKey('encounters.encounterId'), nullable=False)
+    patient_id = db.Column('patientID', db.String(20), db.ForeignKey('patients.patientID'), nullable=False)
     
     # Procedure details
     procedureDateTime = db.Column(db.DateTime, nullable=False)
diff --git a/app/models/referral.py b/app/models/referral.py
index 94310bb..f576e91 100644
--- a/app/models/referral.py
+++ b/app/models/referral.py
@@ -8,6 +8,7 @@ class Referral(db.Model):
     
     id = db.Column('referralID', db.Integer, primary_key=True)
     encounter_id = db.Column('encounterId', db.Integer, db.ForeignKey('encounters.encounterId'), nullable=False)
+    patient_id = db.Column('patientID', db.String(20), db.ForeignKey('patients.patientID'), nullable=False)
     
     # Referral fields from schema
     is_ml_recommended = db.Column(db.Boolean, default=False)
diff --git a/app/models/report.py b/app/models/report.py
index 0f9f0ba..cc424d8 100644
--- a/app/models/report.py
+++ b/app/models/report.py
@@ -8,6 +8,7 @@ class Report(db.Model):
     
     id = db.Column('reportID', db.Integer, primary_key=True)
     user_id = db.Column('userID', db.Integer, db.ForeignKey('users.userID'), nullable=False)
+    patient_id = db.Column('patientID', db.String(20), db.ForeignKey('patients.patientID'), nullable=False)
     report_date = db.Column('reportDateTime', db.DateTime, nullable=False)
     report_title = db.Column('reportTitle', db.String(100), nullable=False)
     report_content = db.Column('reportContent', db.Text)
diff --git a/app/routes/patients.py b/app/routes/patients.py
index 77752d6..a9aa611 100644
--- a/app/routes/patients.py
+++ b/app/routes/patients.py
@@ -87,12 +87,12 @@ def patient_detail(patient_id):
     
     # Get latest measurements
     latest_measurement = PhysiologicalMeasurement.query.filter_by(patient_id=patient.id).order_by(
-        desc(PhysiologicalMeasurement.measurement_date)
+        desc(PhysiologicalMeasurement.measurementDateTime)
     ).first()
     
     # Get patient's measurements history
     measurements = PhysiologicalMeasurement.query.filter_by(patient_id=patient.id).order_by(
-        PhysiologicalMeasurement.measurement_date
+        PhysiologicalMeasurement.measurementDateTime
     ).all()
     
     # Get patient's referrals
@@ -112,7 +112,7 @@ def patient_detail(patient_id):
     
     # Get patient's encounters
     encounters = Encounter.query.filter_by(patient_id=patient.id).order_by(
-        desc(Encounter.admission_date)
+        desc(Encounter.admissionDateTime)
     ).all()
     
     return render_template(
@@ -202,7 +202,7 @@ def new_measurement(patient_id):
             bmi=float(request.form.get('bmi')) if request.form.get('bmi') else None,
             fio2=float(request.form.get('fio2')) if request.form.get('fio2') else None,
             tidal_volume=float(request.form.get('tidal_volume')) if request.form.get('tidal_volume') else None,
-            measurement_date=datetime.now(),
+            measurementDateTime=datetime.now(),
             notes=request.form.get('notes')
         )
         
diff --git a/app/routes/report.py b/app/routes/report.py
index e289a91..8456789 100644
--- a/app/routes/report.py
+++ b/app/routes/report.py
@@ -330,7 +330,7 @@ def generate():
         bmi_category,
         func.count().label('count')
     ).filter(
-        PhysiologicalMeasurement.measurement_date.between(start_date, end_date)
+        PhysiologicalMeasurement.measurementDateTime.between(start_date, end_date)
     ).group_by(bmi_category).all()
     
     # BMI statistics
@@ -508,7 +508,7 @@ def create_stats_report(report_type):
         bmi_category,
         func.count().label('count')
     ).filter(
-        PhysiologicalMeasurement.measurement_date.between(start_date, end_date)
+        PhysiologicalMeasurement.measurementDateTime.between(start_date, end_date)
     ).group_by(bmi_category).all()
     
     # BMI statistics
diff --git a/app/templates/patient_detail.html b/app/templates/patient_detail.html
index 9f5f6c0..7d27fe5 100644
--- a/app/templates/patient_detail.html
+++ b/app/templates/patient_detail.html
@@ -11,7 +11,7 @@
                 <ol class="flex items-center space-x-4">
                     <li>
                         <div>
-                            <a href="{{ url_for('routes.dashboard') }}" class="text-gray-400 hover:text-gray-500 transition duration-150">
+                            <a href="{{ url_for('dashboard.index') }}" class="text-gray-400 hover:text-gray-500 transition duration-150">
                                 <i class="fas fa-home"></i>
                                 <span class="sr-only">Dashboard</span>
                             </a>
@@ -20,7 +20,7 @@
                     <li>
                         <div class="flex items-center">
                             <i class="fas fa-chevron-right text-gray-400 text-sm"></i>
-                            <a href="{{ url_for('routes.patients') }}" class="ml-4 text-sm font-medium text-gray-500 hover:text-gray-700 transition duration-150">Bệnh nhân</a>
+                            <a href="{{ url_for('patients.index') }}" class="ml-4 text-sm font-medium text-gray-500 hover:text-gray-700 transition duration-150">Bệnh nhân</a>
                         </div>
                     </li>
                     <li>
diff --git a/app/templates/upload.html b/app/templates/upload.html
index d12ca9a..b4e2b5f 100644
--- a/app/templates/upload.html
+++ b/app/templates/upload.html
@@ -20,7 +20,7 @@
         <div class="lg:col-span-2">
             <div class="bg-white shadow rounded-lg transition-all duration-300 hover:shadow-lg animate-fade-in">
                 <div class="px-4 py-5 sm:p-6">
-                    <form action="{{ url_for('routes.upload') }}" method="post" enctype="multipart/form-data" id="uploadForm">
+                    <form action="{{ url_for('upload.index') }}" method="post" enctype="multipart/form-data" id="uploadForm">
                         <div class="space-y-6">
                             <div>
                                 <h3 class="text-lg leading-6 font-medium text-gray-900 mb-4">Tải lên tệp CSV</h3>
diff --git a/init_database.py b/init_database.py
index 58438a5..be6e354 100644
--- a/init_database.py
+++ b/init_database.py
@@ -65,9 +65,176 @@ def init_tables_and_admin():
         app = create_app()
         
         with app.app_context():
-            # Tạo tất cả bảng từ các mô hình
+            # Xóa các bảng hiện có để tạo lại với cấu trúc mới
+            try:
+                # Xóa các bảng theo thứ tự để tránh lỗi khóa ngoại
+                db.session.execute(db.text("SET FOREIGN_KEY_CHECKS = 0"))
+                
+                # Xóa các bảng có phụ thuộc
+                db.session.execute(db.text("DROP TABLE IF EXISTS physiologicalmeasurements"))
+                db.session.execute(db.text("DROP TABLE IF EXISTS procedures"))
+                db.session.execute(db.text("DROP TABLE IF EXISTS referrals"))
+                db.session.execute(db.text("DROP TABLE IF EXISTS reports"))
+                db.session.execute(db.text("DROP TABLE IF EXISTS encounters"))
+                
+                # Xóa bảng chính
+                db.session.execute(db.text("DROP TABLE IF EXISTS patients"))
+                
+                db.session.execute(db.text("SET FOREIGN_KEY_CHECKS = 1"))
+                db.session.commit()
+                print("Dropped existing tables to recreate schema.")
+            except Exception as e:
+                db.session.rollback()
+                print(f"Error dropping tables: {str(e)}")
+            
+            # Tạo tất cả bảng từ các mô hình với cấu trúc mới
             db.create_all()
-            print("All database tables created successfully.")
+            print("All database tables created successfully with new schema.")
+            
+            # Thêm các trường cần thiết vào bảng uploadedfiles
+            try:
+                db.session.execute(db.text("ALTER TABLE uploadedfiles ADD COLUMN original_filename VARCHAR(256) DEFAULT ''"))
+                db.session.commit()
+                print("Added original_filename column to uploadedfiles table.")
+            except Exception as e:
+                db.session.rollback()
+                print(f"Note: {str(e)}")
+                
+            try:
+                db.session.execute(db.text("ALTER TABLE uploadedfiles ADD COLUMN file_size INT DEFAULT 0"))
+                db.session.commit()
+                print("Added file_size column to uploadedfiles table.")
+            except Exception as e:
+                db.session.rollback()
+                print(f"Note: {str(e)}")
+                
+            try:
+                db.session.execute(db.text("ALTER TABLE uploadedfiles ADD COLUMN file_type VARCHAR(64) DEFAULT 'csv'"))
+                db.session.commit()
+                print("Added file_type column to uploadedfiles table.")
+            except Exception as e:
+                db.session.rollback()
+                print(f"Note: {str(e)}")
+                
+            try:
+                db.session.execute(db.text("ALTER TABLE uploadedfiles ADD COLUMN delimiter VARCHAR(10) DEFAULT ','"))
+                db.session.commit()
+                print("Added delimiter column to uploadedfiles table.")
+            except Exception as e:
+                db.session.rollback()
+                print(f"Note: {str(e)}")
+                
+            try:
+                db.session.execute(db.text("ALTER TABLE uploadedfiles ADD COLUMN encoding VARCHAR(20) DEFAULT 'utf-8'"))
+                db.session.commit()
+                print("Added encoding column to uploadedfiles table.")
+            except Exception as e:
+                db.session.rollback()
+                print(f"Note: {str(e)}")
+                
+            try:
+                db.session.execute(db.text("ALTER TABLE uploadedfiles ADD COLUMN status VARCHAR(20) DEFAULT 'pending'"))
+                db.session.commit()
+                print("Added status column to uploadedfiles table.")
+            except Exception as e:
+                db.session.rollback()
+                print(f"Note: {str(e)}")
+                
+            try:
+                db.session.execute(db.text("ALTER TABLE uploadedfiles ADD COLUMN process_start DATETIME NULL"))
+                db.session.commit()
+                print("Added process_start column to uploadedfiles table.")
+            except Exception as e:
+                db.session.rollback()
+                print(f"Note: {str(e)}")
+                
+            try:
+                db.session.execute(db.text("ALTER TABLE uploadedfiles ADD COLUMN process_end DATETIME NULL"))
+                db.session.commit()
+                print("Added process_end column to uploadedfiles table.")
+            except Exception as e:
+                db.session.rollback()
+                print(f"Note: {str(e)}")
+                
+            try:
+                db.session.execute(db.text("ALTER TABLE uploadedfiles ADD COLUMN total_records INT DEFAULT 0"))
+                db.session.commit()
+                print("Added total_records column to uploadedfiles table.")
+            except Exception as e:
+                db.session.rollback()
+                print(f"Note: {str(e)}")
+                
+            try:
+                db.session.execute(db.text("ALTER TABLE uploadedfiles ADD COLUMN processed_records INT DEFAULT 0"))
+                db.session.commit()
+                print("Added processed_records column to uploadedfiles table.")
+            except Exception as e:
+                db.session.rollback()
+                print(f"Note: {str(e)}")
+                
+            try:
+                db.session.execute(db.text("ALTER TABLE uploadedfiles ADD COLUMN error_records INT DEFAULT 0"))
+                db.session.commit()
+                print("Added error_records column to uploadedfiles table.")
+            except Exception as e:
+                db.session.rollback()
+                print(f"Note: {str(e)}")
+                
+            try:
+                db.session.execute(db.text("ALTER TABLE uploadedfiles ADD COLUMN error_details TEXT NULL"))
+                db.session.commit()
+                print("Added error_details column to uploadedfiles table.")
+            except Exception as e:
+                db.session.rollback()
+                print(f"Note: {str(e)}")
+                
+            try:
+                db.session.execute(db.text("ALTER TABLE uploadedfiles ADD COLUMN process_referrals BOOLEAN DEFAULT 0"))
+                db.session.commit()
+                print("Added process_referrals column to uploadedfiles table.")
+            except Exception as e:
+                db.session.rollback()
+                print(f"Note: {str(e)}")
+                
+            try:
+                db.session.execute(db.text("ALTER TABLE uploadedfiles ADD COLUMN description TEXT NULL"))
+                db.session.commit()
+                print("Added description column to uploadedfiles table.")
+            except Exception as e:
+                db.session.rollback()
+                print(f"Note: {str(e)}")
+                
+            try:
+                db.session.execute(db.text("ALTER TABLE uploadedfiles ADD COLUMN notes TEXT NULL"))
+                db.session.commit()
+                print("Added notes column to uploadedfiles table.")
+            except Exception as e:
+                db.session.rollback()
+                print(f"Note: {str(e)}")
+                
+            try:
+                db.session.execute(db.text("ALTER TABLE uploadedfiles ADD COLUMN created_at DATETIME DEFAULT CURRENT_TIMESTAMP"))
+                db.session.commit()
+                print("Added created_at column to uploadedfiles table.")
+            except Exception as e:
+                db.session.rollback()
+                print(f"Note: {str(e)}")
+                
+            try:
+                db.session.execute(db.text("ALTER TABLE uploadedfiles ADD COLUMN updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP"))
+                db.session.commit()
+                print("Added updated_at column to uploadedfiles table.")
+            except Exception as e:
+                db.session.rollback()
+                print(f"Note: {str(e)}")
+                
+            try:
+                db.session.execute(db.text("ALTER TABLE uploadedfiles ADD COLUMN upload_date DATETIME DEFAULT CURRENT_TIMESTAMP"))
+                db.session.commit()
+                print("Added upload_date column to uploadedfiles table.")
+            except Exception as e:
+                db.session.rollback()
+                print(f"Note: {str(e)}")
             
             # Thêm trường status vào bảng reports nếu chưa tồn tại
             try:
diff --git a/requirements.txt b/requirements.txt
index 82778b9..10cbecb 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,4 @@
-# Web framework
+# Web framework và các extension
 Flask==2.2.3
 Flask-SQLAlchemy==3.0.3
 Flask-Migrate==4.0.4
@@ -6,12 +6,17 @@ Flask-Login==0.6.2
 Flask-Bcrypt==1.0.1
 Flask-WTF==1.1.1
 WTForms==3.0.1
+Jinja2==3.1.2
+itsdangerous==2.1.2
+click==8.1.3
+MarkupSafe==2.1.2
 email-validator==2.0.0
 
 # Database
 mysqlclient==2.1.1
 SQLAlchemy==2.0.4
 alembic==1.10.2
+mysql-connector-python==8.0.32
 
 # Data processing and visualization
 pandas==1.5.3
@@ -20,6 +25,14 @@ matplotlib==3.7.1
 openpyxl==3.1.2
 Pillow==9.5.0
 reportlab==4.0.0
+seaborn==0.12.2
+plotly==5.14.1
+
+# File handling
+pyexcel==0.7.0
+pyexcel-xlsx==0.6.0
+pypdf2==3.0.1
+XlsxWriter==3.0.9
 
 # Utilities
 python-dotenv==1.0.0
@@ -31,6 +44,13 @@ requests==2.28.2
 pdfkit==1.0.0
 xlsxwriter==3.0.9
 beautifulsoup4==4.12.0
+lxml==4.9.2
+markdown==3.4.1
+PyYAML==6.0
+python-dateutil==2.8.2
+six==1.16.0
+wrapt==1.15.0
+unicodecsv==0.14.1
 
 # Development & Testing
 pytest==7.3.1
@@ -38,3 +58,6 @@ pytest-flask==1.2.0
 coverage==7.2.2
 black==23.1.0
 flake8==6.0.0
+isort==5.12.0
+autopep8==2.0.2
+mypy==1.1.1
-- 
GitLab