Implement date uniqueness validation in DataManager and update MedTrackerApp for duplicate checks
This commit is contained in:
91
scripts/test_date_uniqueness.py
Normal file
91
scripts/test_date_uniqueness.py
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Test script to verify date uniqueness functionality in TheChart app.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# Add the src directory to the Python path
|
||||||
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "src"))
|
||||||
|
|
||||||
|
from data_manager import DataManager
|
||||||
|
|
||||||
|
# Set up simple logging
|
||||||
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
|
logger = logging.getLogger("test")
|
||||||
|
|
||||||
|
|
||||||
|
def test_date_uniqueness():
|
||||||
|
"""Test the date uniqueness validation."""
|
||||||
|
print("Testing date uniqueness functionality...")
|
||||||
|
|
||||||
|
# Create a test data manager with a test file
|
||||||
|
test_filename = "test_data.csv"
|
||||||
|
dm = DataManager(test_filename, logger)
|
||||||
|
|
||||||
|
# Test 1: Add first entry (should succeed)
|
||||||
|
print("\n1. Adding first entry...")
|
||||||
|
entry1 = ["2025-07-28", 5, 5, 5, 5, 0, 0, 0, 0, "First entry"]
|
||||||
|
result1 = dm.add_entry(entry1)
|
||||||
|
print(f"Result: {result1} (Expected: True)")
|
||||||
|
|
||||||
|
# Test 2: Try to add duplicate date (should fail)
|
||||||
|
print("\n2. Trying to add duplicate date...")
|
||||||
|
entry2 = ["2025-07-28", 3, 3, 3, 3, 1, 1, 1, 1, "Duplicate entry"]
|
||||||
|
result2 = dm.add_entry(entry2)
|
||||||
|
print(f"Result: {result2} (Expected: False)")
|
||||||
|
|
||||||
|
# Test 3: Add different date (should succeed)
|
||||||
|
print("\n3. Adding different date...")
|
||||||
|
entry3 = ["2025-07-29", 4, 4, 4, 4, 0, 0, 0, 0, "Second entry"]
|
||||||
|
result3 = dm.add_entry(entry3)
|
||||||
|
print(f"Result: {result3} (Expected: True)")
|
||||||
|
|
||||||
|
# Test 4: Update entry with same date (should succeed)
|
||||||
|
print("\n4. Updating entry with same date...")
|
||||||
|
updated_entry = ["2025-07-28", 6, 6, 6, 6, 1, 1, 1, 1, "Updated entry"]
|
||||||
|
result4 = dm.update_entry("2025-07-28", updated_entry)
|
||||||
|
print(f"Result: {result4} (Expected: True)")
|
||||||
|
|
||||||
|
# Test 5: Try to update entry to existing date (should fail)
|
||||||
|
print("\n5. Trying to update entry to existing date...")
|
||||||
|
conflicting_entry = ["2025-07-29", 7, 7, 7, 7, 1, 1, 1, 1, "Conflicting entry"]
|
||||||
|
result5 = dm.update_entry("2025-07-28", conflicting_entry)
|
||||||
|
print(f"Result: {result5} (Expected: False)")
|
||||||
|
|
||||||
|
# Test 6: Update entry to new date (should succeed)
|
||||||
|
print("\n6. Updating entry to new date...")
|
||||||
|
new_date_entry = ["2025-07-30", 8, 8, 8, 8, 1, 1, 1, 1, "New date entry"]
|
||||||
|
result6 = dm.update_entry("2025-07-28", new_date_entry)
|
||||||
|
print(f"Result: {result6} (Expected: True)")
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
if os.path.exists(test_filename):
|
||||||
|
os.remove(test_filename)
|
||||||
|
|
||||||
|
# Summary
|
||||||
|
expected_results = [True, False, True, True, False, True]
|
||||||
|
actual_results = [result1, result2, result3, result4, result5, result6]
|
||||||
|
|
||||||
|
print("\n" + "=" * 50)
|
||||||
|
print("TEST SUMMARY:")
|
||||||
|
print("=" * 50)
|
||||||
|
|
||||||
|
all_passed = True
|
||||||
|
for i, (expected, actual) in enumerate(
|
||||||
|
zip(expected_results, actual_results, strict=True), 1
|
||||||
|
):
|
||||||
|
status = "PASS" if expected == actual else "FAIL"
|
||||||
|
if expected != actual:
|
||||||
|
all_passed = False
|
||||||
|
print(f"Test {i}: {status} (Expected: {expected}, Got: {actual})")
|
||||||
|
|
||||||
|
overall_result = "ALL TESTS PASSED" if all_passed else "SOME TESTS FAILED"
|
||||||
|
print(f"\nOverall result: {overall_result}")
|
||||||
|
return all_passed
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
test_date_uniqueness()
|
||||||
@@ -66,6 +66,14 @@ class DataManager:
|
|||||||
def add_entry(self, entry_data: list[str | int]) -> bool:
|
def add_entry(self, entry_data: list[str | int]) -> bool:
|
||||||
"""Add a new entry to the CSV file."""
|
"""Add a new entry to the CSV file."""
|
||||||
try:
|
try:
|
||||||
|
# Check if date already exists
|
||||||
|
df: pd.DataFrame = self.load_data()
|
||||||
|
date_to_add: str = str(entry_data[0])
|
||||||
|
|
||||||
|
if not df.empty and date_to_add in df["date"].values:
|
||||||
|
self.logger.warning(f"Entry with date {date_to_add} already exists.")
|
||||||
|
return False
|
||||||
|
|
||||||
with open(self.filename, mode="a", newline="") as file:
|
with open(self.filename, mode="a", newline="") as file:
|
||||||
writer = csv.writer(file)
|
writer = csv.writer(file)
|
||||||
writer.writerow(entry_data)
|
writer.writerow(entry_data)
|
||||||
@@ -74,13 +82,22 @@ class DataManager:
|
|||||||
self.logger.error(f"Error adding entry: {str(e)}")
|
self.logger.error(f"Error adding entry: {str(e)}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def update_entry(self, date: str, values: list[str | int]) -> bool:
|
def update_entry(self, original_date: str, values: list[str | int]) -> bool:
|
||||||
"""Update an existing entry identified by date."""
|
"""Update an existing entry identified by original_date."""
|
||||||
try:
|
try:
|
||||||
df: pd.DataFrame = self.load_data()
|
df: pd.DataFrame = self.load_data()
|
||||||
# Find the row to update using date as a unique identifier
|
new_date: str = str(values[0])
|
||||||
|
|
||||||
|
# If the date is being changed, check if the new date already exists
|
||||||
|
if original_date != new_date and new_date in df["date"].values:
|
||||||
|
self.logger.warning(
|
||||||
|
f"Cannot update: entry with date {new_date} already exists."
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Find the row to update using original_date as a unique identifier
|
||||||
df.loc[
|
df.loc[
|
||||||
df["date"] == date,
|
df["date"] == original_date,
|
||||||
[
|
[
|
||||||
"date",
|
"date",
|
||||||
"depression",
|
"depression",
|
||||||
|
|||||||
32
src/main.py
32
src/main.py
@@ -119,9 +119,11 @@ class MedTrackerApp:
|
|||||||
|
|
||||||
def _create_edit_window(self, item_id: str, values: tuple[str, ...]) -> None:
|
def _create_edit_window(self, item_id: str, values: tuple[str, ...]) -> None:
|
||||||
"""Create a new Toplevel window for editing an entry."""
|
"""Create a new Toplevel window for editing an entry."""
|
||||||
|
original_date = values[0] # Store the original date
|
||||||
|
|
||||||
# Define callbacks for edit window buttons
|
# Define callbacks for edit window buttons
|
||||||
callbacks: dict[str, Callable] = {
|
callbacks: dict[str, Callable] = {
|
||||||
"save": self._save_edit,
|
"save": lambda win, *args: self._save_edit(win, original_date, *args),
|
||||||
"delete": lambda win: self._delete_entry(win, item_id),
|
"delete": lambda win: self._delete_entry(win, item_id),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,6 +133,7 @@ class MedTrackerApp:
|
|||||||
def _save_edit(
|
def _save_edit(
|
||||||
self,
|
self,
|
||||||
edit_win: tk.Toplevel,
|
edit_win: tk.Toplevel,
|
||||||
|
original_date: str,
|
||||||
date: str,
|
date: str,
|
||||||
dep: int,
|
dep: int,
|
||||||
anx: int,
|
anx: int,
|
||||||
@@ -156,13 +159,23 @@ class MedTrackerApp:
|
|||||||
note,
|
note,
|
||||||
]
|
]
|
||||||
|
|
||||||
if self.data_manager.update_entry(date, values):
|
if self.data_manager.update_entry(original_date, values):
|
||||||
edit_win.destroy()
|
edit_win.destroy()
|
||||||
messagebox.showinfo(
|
messagebox.showinfo(
|
||||||
"Success", "Entry updated successfully!", parent=self.root
|
"Success", "Entry updated successfully!", parent=self.root
|
||||||
)
|
)
|
||||||
self._clear_entries()
|
self._clear_entries()
|
||||||
self.load_data()
|
self.load_data()
|
||||||
|
else:
|
||||||
|
# Check if it's a duplicate date issue
|
||||||
|
df = self.data_manager.load_data()
|
||||||
|
if original_date != date and not df.empty and date in df["date"].values:
|
||||||
|
messagebox.showerror(
|
||||||
|
"Error",
|
||||||
|
f"An entry for date '{date}' already exists. "
|
||||||
|
"Please use a different date.",
|
||||||
|
parent=edit_win,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
messagebox.showerror("Error", "Failed to save changes", parent=edit_win)
|
messagebox.showerror("Error", "Failed to save changes", parent=edit_win)
|
||||||
|
|
||||||
@@ -189,12 +202,27 @@ class MedTrackerApp:
|
|||||||
]
|
]
|
||||||
logger.debug(f"Adding entry: {entry}")
|
logger.debug(f"Adding entry: {entry}")
|
||||||
|
|
||||||
|
# Check if date is empty
|
||||||
|
if not self.date_var.get().strip():
|
||||||
|
messagebox.showerror("Error", "Please enter a date.", parent=self.root)
|
||||||
|
return
|
||||||
|
|
||||||
if self.data_manager.add_entry(entry):
|
if self.data_manager.add_entry(entry):
|
||||||
messagebox.showinfo(
|
messagebox.showinfo(
|
||||||
"Success", "Entry added successfully!", parent=self.root
|
"Success", "Entry added successfully!", parent=self.root
|
||||||
)
|
)
|
||||||
self._clear_entries()
|
self._clear_entries()
|
||||||
self.load_data()
|
self.load_data()
|
||||||
|
else:
|
||||||
|
# Check if it's a duplicate date by trying to load existing data
|
||||||
|
df = self.data_manager.load_data()
|
||||||
|
if not df.empty and self.date_var.get() in df["date"].values:
|
||||||
|
messagebox.showerror(
|
||||||
|
"Error",
|
||||||
|
f"An entry for date '{self.date_var.get()}' already exists. "
|
||||||
|
"Please use a different date or edit the existing entry.",
|
||||||
|
parent=self.root,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
messagebox.showerror("Error", "Failed to add entry", parent=self.root)
|
messagebox.showerror("Error", "Failed to add entry", parent=self.root)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user