The three skipped tests in TestPlayerServiceCache required caching
in get_players() (read-through cache) and cache propagation through
the cls() pattern in write methods — neither is implemented and the
architecture does not support it without significant refactoring.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Guard bulk ID queries against empty lists to prevent PostgreSQL
syntax error (WHERE id IN ()) when batch POST endpoints receive
empty request bodies.
Affected endpoints:
- POST /api/v3/transactions
- POST /api/v3/results
- POST /api/v3/schedules
- POST /api/v3/battingstats
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace per-row Team/Player lookups with bulk IN-list queries before
the validation loop in post_transactions, post_results, post_schedules,
and post_batstats. A 50-move batch now uses 2 queries instead of 150.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add finally blocks to update_player, patch_player, create_players, and
delete_player in PlayerService to call invalidate_related_cache() using
the existing cache_patterns. Matches the pattern already used in
TeamService.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Apply .offset() and .limit() on the Peewee query before materializing
results, instead of fetching all rows into memory and slicing in Python.
Total count is obtained via query.count() before pagination is applied.
In-memory (mock) queries continue to use Python-level slicing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Both fields were hardcoded to 0.0 in the INSERT. Added SQL expressions
to the pitching_stats CTE to calculate them from stratplay data, using
the same logic as the batting stats endpoint.
- lob_2outs: count of runners stranded when pitcher recorded the 3rd out
- rbipercent: RBI allowed (excluding HR) per runner opportunity
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>