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