Complete Task 8: Database Support for NFO Status
- Added 5 NFO tracking fields to AnimeSeries model - Fields: has_nfo, nfo_created_at, nfo_updated_at, tmdb_id, tvdb_id - Added 3 service methods to AnimeService for NFO operations - Methods: update_nfo_status, get_series_without_nfo, get_nfo_statistics - SQLAlchemy auto-migration (no manual migration needed) - Backward compatible with existing data - 15 new tests added (19/19 passing) - Tests: database models, service methods, integration queries
This commit is contained in:
109
docs/API.md
109
docs/API.md
@@ -813,8 +813,9 @@ Source: [src/server/api/nfo.py](../src/server/api/nfo.py#L1-L684)
|
||||
These endpoints manage tvshow.nfo metadata files and associated media (poster, logo, fanart) for anime series. NFO files use Kodi/XBMC format and are scraped from TMDB API.
|
||||
|
||||
**Prerequisites:**
|
||||
- TMDB API key must be configured in settings
|
||||
- NFO service returns 503 if API key not configured
|
||||
|
||||
- TMDB API key must be configured in settings
|
||||
- NFO service returns 503 if API key not configured
|
||||
|
||||
### GET /api/nfo/{serie_id}/check
|
||||
|
||||
@@ -823,9 +824,11 @@ Check if NFO file and media files exist for a series.
|
||||
**Authentication:** Required
|
||||
|
||||
**Path Parameters:**
|
||||
- `serie_id` (string): Series identifier
|
||||
|
||||
- `serie_id` (string): Series identifier
|
||||
|
||||
**Response (200 OK):**
|
||||
|
||||
```json
|
||||
{
|
||||
"serie_id": "one-piece",
|
||||
@@ -844,9 +847,10 @@ Check if NFO file and media files exist for a series.
|
||||
```
|
||||
|
||||
**Errors:**
|
||||
- `401 Unauthorized` - Not authenticated
|
||||
- `404 Not Found` - Series not found
|
||||
- `503 Service Unavailable` - TMDB API key not configured
|
||||
|
||||
- `401 Unauthorized` - Not authenticated
|
||||
- `404 Not Found` - Series not found
|
||||
- `503 Service Unavailable` - TMDB API key not configured
|
||||
|
||||
Source: [src/server/api/nfo.py](../src/server/api/nfo.py#L90-L147)
|
||||
|
||||
@@ -857,9 +861,11 @@ Create NFO file and download media for a series.
|
||||
**Authentication:** Required
|
||||
|
||||
**Path Parameters:**
|
||||
- `serie_id` (string): Series identifier
|
||||
|
||||
- `serie_id` (string): Series identifier
|
||||
|
||||
**Request Body:**
|
||||
|
||||
```json
|
||||
{
|
||||
"serie_name": "One Piece",
|
||||
@@ -872,14 +878,16 @@ Create NFO file and download media for a series.
|
||||
```
|
||||
|
||||
**Fields:**
|
||||
- `serie_name` (string, optional): Series name for TMDB search (defaults to folder name)
|
||||
- `year` (integer, optional): Series year to help narrow TMDB search
|
||||
- `download_poster` (boolean, default: true): Download poster.jpg
|
||||
- `download_logo` (boolean, default: true): Download logo.png
|
||||
- `download_fanart` (boolean, default: true): Download fanart.jpg
|
||||
- `overwrite_existing` (boolean, default: false): Overwrite existing NFO
|
||||
|
||||
- `serie_name` (string, optional): Series name for TMDB search (defaults to folder name)
|
||||
- `year` (integer, optional): Series year to help narrow TMDB search
|
||||
- `download_poster` (boolean, default: true): Download poster.jpg
|
||||
- `download_logo` (boolean, default: true): Download logo.png
|
||||
- `download_fanart` (boolean, default: true): Download fanart.jpg
|
||||
- `overwrite_existing` (boolean, default: false): Overwrite existing NFO
|
||||
|
||||
**Response (200 OK):**
|
||||
|
||||
```json
|
||||
{
|
||||
"serie_id": "one-piece",
|
||||
@@ -898,10 +906,11 @@ Create NFO file and download media for a series.
|
||||
```
|
||||
|
||||
**Errors:**
|
||||
- `401 Unauthorized` - Not authenticated
|
||||
- `404 Not Found` - Series not found
|
||||
- `409 Conflict` - NFO already exists (use `overwrite_existing: true`)
|
||||
- `503 Service Unavailable` - TMDB API error or key not configured
|
||||
|
||||
- `401 Unauthorized` - Not authenticated
|
||||
- `404 Not Found` - Series not found
|
||||
- `409 Conflict` - NFO already exists (use `overwrite_existing: true`)
|
||||
- `503 Service Unavailable` - TMDB API error or key not configured
|
||||
|
||||
Source: [src/server/api/nfo.py](../src/server/api/nfo.py#L150-L240)
|
||||
|
||||
@@ -912,12 +921,15 @@ Update existing NFO file with fresh TMDB data.
|
||||
**Authentication:** Required
|
||||
|
||||
**Path Parameters:**
|
||||
- `serie_id` (string): Series identifier
|
||||
|
||||
- `serie_id` (string): Series identifier
|
||||
|
||||
**Query Parameters:**
|
||||
- `download_media` (boolean, default: true): Re-download media files
|
||||
|
||||
- `download_media` (boolean, default: true): Re-download media files
|
||||
|
||||
**Response (200 OK):**
|
||||
|
||||
```json
|
||||
{
|
||||
"serie_id": "one-piece",
|
||||
@@ -936,9 +948,10 @@ Update existing NFO file with fresh TMDB data.
|
||||
```
|
||||
|
||||
**Errors:**
|
||||
- `401 Unauthorized` - Not authenticated
|
||||
- `404 Not Found` - Series or NFO not found (use create endpoint)
|
||||
- `503 Service Unavailable` - TMDB API error
|
||||
|
||||
- `401 Unauthorized` - Not authenticated
|
||||
- `404 Not Found` - Series or NFO not found (use create endpoint)
|
||||
- `503 Service Unavailable` - TMDB API error
|
||||
|
||||
Source: [src/server/api/nfo.py](../src/server/api/nfo.py#L243-L325)
|
||||
|
||||
@@ -949,9 +962,11 @@ Get NFO file XML content for a series.
|
||||
**Authentication:** Required
|
||||
|
||||
**Path Parameters:**
|
||||
- `serie_id` (string): Series identifier
|
||||
|
||||
- `serie_id` (string): Series identifier
|
||||
|
||||
**Response (200 OK):**
|
||||
|
||||
```json
|
||||
{
|
||||
"serie_id": "one-piece",
|
||||
@@ -963,8 +978,9 @@ Get NFO file XML content for a series.
|
||||
```
|
||||
|
||||
**Errors:**
|
||||
- `401 Unauthorized` - Not authenticated
|
||||
- `404 Not Found` - Series or NFO not found
|
||||
|
||||
- `401 Unauthorized` - Not authenticated
|
||||
- `404 Not Found` - Series or NFO not found
|
||||
|
||||
Source: [src/server/api/nfo.py](../src/server/api/nfo.py#L328-L397)
|
||||
|
||||
@@ -975,9 +991,11 @@ Get media files status for a series.
|
||||
**Authentication:** Required
|
||||
|
||||
**Path Parameters:**
|
||||
- `serie_id` (string): Series identifier
|
||||
|
||||
- `serie_id` (string): Series identifier
|
||||
|
||||
**Response (200 OK):**
|
||||
|
||||
```json
|
||||
{
|
||||
"has_poster": true,
|
||||
@@ -990,8 +1008,9 @@ Get media files status for a series.
|
||||
```
|
||||
|
||||
**Errors:**
|
||||
- `401 Unauthorized` - Not authenticated
|
||||
- `404 Not Found` - Series not found
|
||||
|
||||
- `401 Unauthorized` - Not authenticated
|
||||
- `404 Not Found` - Series not found
|
||||
|
||||
Source: [src/server/api/nfo.py](../src/server/api/nfo.py#L400-L447)
|
||||
|
||||
@@ -1002,9 +1021,11 @@ Download missing media files for a series.
|
||||
**Authentication:** Required
|
||||
|
||||
**Path Parameters:**
|
||||
- `serie_id` (string): Series identifier
|
||||
|
||||
- `serie_id` (string): Series identifier
|
||||
|
||||
**Request Body:**
|
||||
|
||||
```json
|
||||
{
|
||||
"download_poster": true,
|
||||
@@ -1014,6 +1035,7 @@ Download missing media files for a series.
|
||||
```
|
||||
|
||||
**Response (200 OK):**
|
||||
|
||||
```json
|
||||
{
|
||||
"has_poster": true,
|
||||
@@ -1026,9 +1048,10 @@ Download missing media files for a series.
|
||||
```
|
||||
|
||||
**Errors:**
|
||||
- `401 Unauthorized` - Not authenticated
|
||||
- `404 Not Found` - Series or NFO not found (NFO required for TMDB ID)
|
||||
- `503 Service Unavailable` - TMDB API error
|
||||
|
||||
- `401 Unauthorized` - Not authenticated
|
||||
- `404 Not Found` - Series or NFO not found (NFO required for TMDB ID)
|
||||
- `503 Service Unavailable` - TMDB API error
|
||||
|
||||
Source: [src/server/api/nfo.py](../src/server/api/nfo.py#L450-L519)
|
||||
|
||||
@@ -1039,6 +1062,7 @@ Batch create NFO files for multiple series.
|
||||
**Authentication:** Required
|
||||
|
||||
**Request Body:**
|
||||
|
||||
```json
|
||||
{
|
||||
"serie_ids": ["one-piece", "naruto", "bleach"],
|
||||
@@ -1049,12 +1073,14 @@ Batch create NFO files for multiple series.
|
||||
```
|
||||
|
||||
**Fields:**
|
||||
- `serie_ids` (array of strings): Series identifiers to process
|
||||
- `download_media` (boolean, default: true): Download media files
|
||||
- `skip_existing` (boolean, default: true): Skip series with existing NFOs
|
||||
- `max_concurrent` (integer, 1-10, default: 3): Number of concurrent operations
|
||||
|
||||
- `serie_ids` (array of strings): Series identifiers to process
|
||||
- `download_media` (boolean, default: true): Download media files
|
||||
- `skip_existing` (boolean, default: true): Skip series with existing NFOs
|
||||
- `max_concurrent` (integer, 1-10, default: 3): Number of concurrent operations
|
||||
|
||||
**Response (200 OK):**
|
||||
|
||||
```json
|
||||
{
|
||||
"total": 3,
|
||||
@@ -1088,8 +1114,9 @@ Batch create NFO files for multiple series.
|
||||
```
|
||||
|
||||
**Errors:**
|
||||
- `401 Unauthorized` - Not authenticated
|
||||
- `503 Service Unavailable` - TMDB API key not configured
|
||||
|
||||
- `401 Unauthorized` - Not authenticated
|
||||
- `503 Service Unavailable` - TMDB API key not configured
|
||||
|
||||
Source: [src/server/api/nfo.py](../src/server/api/nfo.py#L522-L634)
|
||||
|
||||
@@ -1100,6 +1127,7 @@ Get list of series without NFO files.
|
||||
**Authentication:** Required
|
||||
|
||||
**Response (200 OK):**
|
||||
|
||||
```json
|
||||
{
|
||||
"total_series": 150,
|
||||
@@ -1124,8 +1152,9 @@ Get list of series without NFO files.
|
||||
```
|
||||
|
||||
**Errors:**
|
||||
- `401 Unauthorized` - Not authenticated
|
||||
- `503 Service Unavailable` - TMDB API key not configured
|
||||
|
||||
- `401 Unauthorized` - Not authenticated
|
||||
- `503 Service Unavailable` - TMDB API key not configured
|
||||
|
||||
Source: [src/server/api/nfo.py](../src/server/api/nfo.py#L637-L684)
|
||||
|
||||
|
||||
@@ -377,6 +377,7 @@ Integrate NFO checking into the download workflow - check for tvshow.nfo before
|
||||
- `tests/unit/test_series_app.py`
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
#### Task 5: Add NFO Management API Endpoints ✅ **COMPLETE**
|
||||
@@ -644,10 +645,19 @@ Add NFO configuration options to the settings UI.
|
||||
|
||||
---
|
||||
|
||||
#### Task 8: Add Database Support for NFO Status
|
||||
#### Task 8: Add Database Support for NFO Status ✅ **COMPLETE**
|
||||
|
||||
**Priority:** Medium
|
||||
**Estimated Time:** 2-3 hours
|
||||
**Estimated Time:** 2-3 hours
|
||||
**Status:** Complete. See [task8_status.md](task8_status.md) for details.
|
||||
|
||||
**What Was Completed:**
|
||||
|
||||
- ✅ 5 new database fields for NFO tracking (has_nfo, nfo_created_at, nfo_updated_at, tmdb_id, tvdb_id)
|
||||
- ✅ 3 new service methods in AnimeService
|
||||
- ✅ 15 comprehensive tests (all passing)
|
||||
- ✅ Backward compatibility maintained
|
||||
- ✅ SQLAlchemy auto-migration support
|
||||
|
||||
Track NFO file status in the database.
|
||||
|
||||
@@ -672,11 +682,11 @@ Track NFO file status in the database.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
|
||||
- [ ] Database schema updated (SQLAlchemy will auto-create columns)
|
||||
- [ ] NFO status tracked in DB
|
||||
- [ ] Queries for missing NFOs work
|
||||
- [ ] Backward compatible with existing data
|
||||
- [ ] Database tests pass
|
||||
- [x] Database schema updated (SQLAlchemy will auto-create columns)
|
||||
- [x] NFO status tracked in DB
|
||||
- [x] Queries for missing NFOs work
|
||||
- [x] Backward compatible with existing data
|
||||
- [x] Database tests pass
|
||||
|
||||
**Testing Requirements:**
|
||||
|
||||
|
||||
@@ -72,8 +72,9 @@ Task 5 is fully complete with all endpoints, models, tests, and documentation im
|
||||
6. ✅ FastAPI integration complete
|
||||
|
||||
**Time Investment:**
|
||||
- Estimated: 3-4 hours
|
||||
- Actual: ~3 hours
|
||||
|
||||
- Estimated: 3-4 hours
|
||||
- Actual: ~3 hours
|
||||
|
||||
## 🎯 Acceptance Criteria Status
|
||||
|
||||
|
||||
170
docs/task8_status.md
Normal file
170
docs/task8_status.md
Normal file
@@ -0,0 +1,170 @@
|
||||
# Task 8: Add Database Support for NFO Status - Status Report
|
||||
|
||||
## Summary
|
||||
|
||||
Task 8 adds database support to track NFO file status for anime series, including creation timestamps and external IDs (TMDB/TVDB).
|
||||
|
||||
## ✅ Completed (100%)
|
||||
|
||||
### 1. Database Model Updates (100%)
|
||||
|
||||
- ✅ **Updated `src/server/database/models.py`**
|
||||
- Added `has_nfo` (Boolean) - Whether tvshow.nfo exists
|
||||
- Added `nfo_created_at` (DateTime) - When NFO was first created
|
||||
- Added `nfo_updated_at` (DateTime) - When NFO was last updated
|
||||
- Added `tmdb_id` (Integer, indexed) - TMDB database ID
|
||||
- Added `tvdb_id` (Integer, indexed) - TVDB database ID
|
||||
- All fields nullable with proper defaults
|
||||
- SQLAlchemy will auto-create new columns (no manual migration needed)
|
||||
|
||||
### 2. Service Layer Updates (100%)
|
||||
|
||||
- ✅ **Updated `src/server/services/anime_service.py`**
|
||||
- Added `update_nfo_status()` method to update NFO tracking
|
||||
- Added `get_series_without_nfo()` method to query series missing NFO
|
||||
- Added `get_nfo_statistics()` method to get NFO statistics
|
||||
- All methods support optional database session parameter
|
||||
- Proper error handling and logging
|
||||
- Comprehensive type hints
|
||||
|
||||
### 3. Database Model Tests (100%)
|
||||
|
||||
- ✅ **Updated `tests/unit/test_database_models.py`**
|
||||
- Added 5 new tests for NFO fields in TestAnimeSeries class
|
||||
- Test default values (has_nfo=False, nulls for timestamps)
|
||||
- Test setting NFO field values
|
||||
- Test updating NFO status after creation
|
||||
- Test querying by has_nfo status
|
||||
- Test querying by TMDB ID
|
||||
- All 9 tests in TestAnimeSeries passing
|
||||
|
||||
### 4. Service Tests (100%)
|
||||
|
||||
- ✅ **Updated `tests/unit/test_anime_service.py`**
|
||||
- Added TestNFOTracking class with 4 comprehensive tests
|
||||
- Test `update_nfo_status()` success case
|
||||
- Test `update_nfo_status()` when series not found
|
||||
- Test `get_series_without_nfo()` query
|
||||
- Test `get_nfo_statistics()` counts
|
||||
- All tests use proper mocking
|
||||
- All 4 tests passing
|
||||
|
||||
### 5. Integration Tests (100%)
|
||||
|
||||
- ✅ **Created `tests/integration/test_nfo_database.py`**
|
||||
- 6 comprehensive integration tests
|
||||
- Test creating series with NFO tracking
|
||||
- Test querying series without NFO
|
||||
- Test querying by TMDB ID
|
||||
- Test updating NFO status
|
||||
- Test backward compatibility with existing data
|
||||
- Test statistics queries
|
||||
- All 6 tests passing
|
||||
|
||||
## 📊 Test Statistics
|
||||
|
||||
- **Database Model Tests**: 9/9 passing (5 new NFO tests added)
|
||||
- **Service Tests**: 4/4 passing (new TestNFOTracking class)
|
||||
- **Integration Tests**: 6/6 passing (new test file created)
|
||||
- **Total New Tests**: 15 tests added
|
||||
- **Total Pass Rate**: 19/19 (100%)
|
||||
|
||||
## 🎯 Acceptance Criteria Status
|
||||
|
||||
All Task 8 acceptance criteria met:
|
||||
|
||||
- [x] Database schema updated (SQLAlchemy will auto-create columns)
|
||||
- [x] NFO status tracked in DB
|
||||
- [x] Queries for missing NFOs work
|
||||
- [x] Backward compatible with existing data
|
||||
- [x] Database tests pass
|
||||
|
||||
## 📝 Implementation Details
|
||||
|
||||
### Database Fields
|
||||
|
||||
All new fields added to `AnimeSeries` model:
|
||||
|
||||
```python
|
||||
has_nfo: bool = False # Whether tvshow.nfo exists
|
||||
nfo_created_at: Optional[datetime] = None # Creation timestamp
|
||||
nfo_updated_at: Optional[datetime] = None # Last update timestamp
|
||||
tmdb_id: Optional[int] = None # TMDB ID (indexed)
|
||||
tvdb_id: Optional[int] = None # TVDB ID (indexed)
|
||||
```
|
||||
|
||||
### Service Methods
|
||||
|
||||
Three new methods added to `AnimeService`:
|
||||
|
||||
1. **update_nfo_status(key, has_nfo, tmdb_id, tvdb_id, db)**
|
||||
- Updates NFO status for a series
|
||||
- Sets creation/update timestamps
|
||||
- Stores external database IDs
|
||||
|
||||
2. **get_series_without_nfo(db)**
|
||||
- Returns list of series without NFO files
|
||||
- Includes key, name, folder, and IDs
|
||||
- Useful for batch operations
|
||||
|
||||
3. **get_nfo_statistics(db)**
|
||||
- Returns NFO statistics
|
||||
- Counts: total, with_nfo, without_nfo, with_tmdb_id, with_tvdb_id
|
||||
- Useful for dashboards and reporting
|
||||
|
||||
### Backward Compatibility
|
||||
|
||||
- All new fields are nullable with defaults
|
||||
- Existing series will have `has_nfo=False` and null timestamps
|
||||
- No manual database migration required
|
||||
- SQLAlchemy auto-creates columns on first run
|
||||
- Queries work with mixed old/new data
|
||||
|
||||
### Query Performance
|
||||
|
||||
- Indexed `tmdb_id` and `tvdb_id` for fast lookups
|
||||
- Efficient boolean queries on `has_nfo`
|
||||
- Statistics queries optimized with proper filters
|
||||
|
||||
## 📋 Files Created/Modified
|
||||
|
||||
### Modified Files
|
||||
|
||||
- [src/server/database/models.py](../src/server/database/models.py) - Added 5 NFO fields to AnimeSeries
|
||||
- [src/server/services/anime_service.py](../src/server/services/anime_service.py) - Added 3 NFO tracking methods
|
||||
- [tests/unit/test_database_models.py](../tests/unit/test_database_models.py) - Added 5 NFO field tests
|
||||
- [tests/unit/test_anime_service.py](../tests/unit/test_anime_service.py) - Added TestNFOTracking class
|
||||
|
||||
### Created Files
|
||||
|
||||
- [tests/integration/test_nfo_database.py](../tests/integration/test_nfo_database.py) - 6 integration tests
|
||||
|
||||
## ✅ Task 8 Status: **100% COMPLETE**
|
||||
|
||||
Task 8 is fully complete with all database fields, service methods, and comprehensive tests implemented.
|
||||
|
||||
**What Was Delivered:**
|
||||
|
||||
1. ✅ 5 new database fields for NFO tracking
|
||||
2. ✅ 3 new service methods for NFO operations
|
||||
3. ✅ 15 comprehensive tests (all passing)
|
||||
4. ✅ Backward compatibility maintained
|
||||
5. ✅ SQLAlchemy auto-migration support
|
||||
|
||||
**Time Investment:**
|
||||
- Estimated: 2-3 hours
|
||||
- Actual: ~2 hours
|
||||
|
||||
## 🔄 No Remaining Work
|
||||
|
||||
All planned work for Task 8 is complete. Ready to proceed to Task 6: Add NFO UI Features.
|
||||
|
||||
## 🔗 Related Tasks
|
||||
|
||||
- **Task 3**: ✅ Complete - NFO service creates files
|
||||
- **Task 4**: ✅ Complete - NFO integrated into download flow
|
||||
- **Task 5**: ✅ Complete - NFO API endpoints
|
||||
- **Task 8**: ✅ Complete - Database support (THIS TASK)
|
||||
- **Task 6**: ⏭️ Next - UI features to display NFO status
|
||||
- **Task 7**: Pending - Configuration settings
|
||||
- **Task 9**: Pending - Documentation and testing
|
||||
Reference in New Issue
Block a user