Files
TimeTracker/IMPLEMENTATION_SUMMARY_DEFAULT_DATA_SEEDING.md
Dries Peeters 5280cbad2c fix: prevent re-creation of deleted default client and project
Implements persistent flag tracking to ensure default client and project
are only created on fresh installations and never recreated after user
deletion during updates or restarts.

- Added initial_data_seeded flag to InstallationConfig
- Updated all 3 database initialization scripts to check flag
- Added 3 unit tests (all passing)
- Created comprehensive documentation

Fixes issue where defaults were recreated after deletion during updates.
2025-10-23 09:31:39 +02:00

7.7 KiB

Implementation Summary: Default Data Seeding Fix

Issue Resolved

Problem: Default client and project were being re-created after deletion during updates from version 3.2.2 to 3.2.3.

Solution: Implemented a persistent flag-based tracking system to ensure default data is only seeded on fresh database installations.


📋 Changes Made

1. Core Implementation

app/utils/installation.py - Added Tracking Methods

  • Method: is_initial_data_seeded() - Returns bool

    • Checks if initial database data has been created
    • Returns False for new installations
  • Method: mark_initial_data_seeded() - Returns None

    • Marks that initial data has been created
    • Stores timestamp in installation.json
    • Persists across restarts and updates

2. Database Initialization Scripts Updated

docker/init-database.py

  • Imports InstallationConfig
  • Checks flag before creating default project/client
  • Only creates defaults if:
    1. Flag is not set AND
    2. No projects exist in database
  • Marks flag after seeding or if projects exist

docker/init-database-enhanced.py

  • Imports InstallationConfig with proper path handling
  • Checks project count via SQL query
  • Conditional default data creation based on flag
  • Marks flag appropriately

docker/init-database-sql.py

  • Imports InstallationConfig with proper path handling
  • Separates base SQL (admin, settings) from default data SQL
  • Only executes default data SQL if:
    1. Flag is not set AND
    2. Project count is 0
  • Marks flag after seeding

3. Test Coverage

tests/test_installation_config.py - Added 3 New Tests

  1. test_initial_data_seeding_tracking()

    • Verifies flag defaults to False
    • Verifies mark_initial_data_seeded() sets flag to True
    • Verifies flag persists across InstallationConfig instances
  2. test_initial_data_seeding_persistence()

    • Verifies flag is written to installation.json
    • Verifies timestamp is recorded
    • Verifies file format is correct
  3. test_initial_data_seeding_default_value()

    • Verifies new installations default to False

Test Results: All 10 tests pass (3 new + 7 existing)

4. Documentation

Created: docs/DEFAULT_DATA_SEEDING.md

Comprehensive documentation including:

  • Behavior overview (old vs new)
  • Implementation details
  • Testing instructions
  • Troubleshooting guide
  • Reset/recovery procedures
  • Migration notes

Created: DEFAULT_DATA_SEEDING_FIX_CHANGELOG.md

Detailed changelog including:

  • Problem description
  • Solution explanation
  • Files modified
  • Testing performed
  • Migration path
  • Backward compatibility notes

🎯 Behavior Changes

Before (v3.2.2)

1. User deletes "Default Client" and "General" project
2. Container restarts or updates
3. ❌ Default client and project are RECREATED
4. User has to delete them again

After (v3.2.3+)

1. Fresh installation → Creates defaults → Sets flag
2. User deletes defaults → Flag remains set
3. Container restarts or updates → Flag is checked → ✅ Defaults NOT recreated
4. User's choice is respected permanently

📊 Configuration File

data/installation.json

{
  "telemetry_salt": "...",
  "installation_id": "...",
  "setup_complete": true,
  "initial_data_seeded": true,
  "initial_data_seeded_at": "2025-10-23 09:12:34.567890"
}

Verification Checklist

  • InstallationConfig methods added
  • All 3 database initialization scripts updated
  • Unit tests added (3 new tests)
  • All tests pass (10/10)
  • No linter errors
  • Documentation created
  • Changelog created
  • Backward compatible
  • No breaking changes

🔧 Technical Details

Logic Flow

# During database initialization
installation_config = get_installation_config()

if not installation_config.is_initial_data_seeded():
    # First time initialization
    
    if project_count == 0:
        # Truly fresh database
        create_default_client()
        create_default_project()
        installation_config.mark_initial_data_seeded()
    else:
        # Database has projects, just mark as seeded
        installation_config.mark_initial_data_seeded()
else:
    # Already seeded before, skip
    print("Initial data already seeded, skipping...")

State Machine

┌─────────────────────┐
│  Fresh Installation │
│  (no projects)      │
└──────┬──────────────┘
       │
       ├── Create defaults
       ├── Set flag = true
       │
       ▼
┌─────────────────────┐
│  Flag Set = True    │
│  (seeded)           │
└──────┬──────────────┘
       │
       ├── User deletes defaults
       ├── Flag remains true
       │
       ▼
┌─────────────────────┐
│  Next Restart       │
│  Check flag = true  │
└──────┬──────────────┘
       │
       └── Skip creation ✅

🚀 Deployment

For Existing Installations (Upgrading from v3.2.2)

  1. Pull latest code (v3.2.3+)
  2. Restart container
    docker-compose restart
    
  3. First startup:
    • System detects existing projects
    • Sets initial_data_seeded = true
    • Does NOT create defaults
  4. Result: Previously deleted defaults remain deleted

For Fresh Installations

  1. Deploy v3.2.3+
  2. First startup:
    • System detects no projects
    • Creates "Default Client" and "General"
    • Sets initial_data_seeded = true
  3. User can delete defaults
  4. Defaults will never be recreated

🐛 Troubleshooting

Issue: Flag Not Being Set

Symptoms: Default data keeps being created

Check:

# Check if file exists and is writable
ls -la data/installation.json

# Check file contents
cat data/installation.json | grep initial_data_seeded

Fix:

# Ensure directory is writable
chmod 755 data/
chmod 644 data/installation.json

Issue: Need to Reset Defaults

Solution 1 - Remove flag:

# Edit installation.json and remove initial_data_seeded lines
nano data/installation.json

Solution 2 - Fresh start:

# Complete reset
docker-compose down -v
rm data/installation.json
docker-compose up -d

📈 Benefits

  1. User Control: Users can delete defaults without them reappearing
  2. Predictable Behavior: Once deleted, stays deleted
  3. Update Safety: Updates respect user's data choices
  4. Zero Migration: Works automatically on upgrade
  5. Backward Compatible: No manual intervention needed

Modified Files

  • app/utils/installation.py
  • docker/init-database.py
  • docker/init-database-enhanced.py
  • docker/init-database-sql.py
  • tests/test_installation_config.py

Created Files

  • docs/DEFAULT_DATA_SEEDING.md
  • DEFAULT_DATA_SEEDING_FIX_CHANGELOG.md
  • IMPLEMENTATION_SUMMARY_DEFAULT_DATA_SEEDING.md (this file)

Summary

Status: COMPLETE AND TESTED

The default data seeding behavior has been successfully fixed. Users who delete the default client and project will no longer see them re-created during updates or restarts. The implementation uses a persistent flag in the installation configuration that tracks whether initial data has been seeded, providing predictable and user-friendly behavior across all scenarios.

Version: 3.2.3+
Date: October 23, 2025
Tests: 10/10 passing
Linter: No errors
Backward Compatible: Yes