feat: add repositories and reference data seeder

Implements Step 1.5: Creates ULID generation utility, repositories for
all reference types (species, locations, products, feed_types, users),
and an idempotent seeder that populates initial data. Updates CLI seed
command to run migrations and seed data.

Seed data:
- 3 users (ppetru, ines as admin; guest as recorder)
- 8 locations (Strip 1-4, Nursery 1-4)
- 3 species (duck, goose active; sheep inactive)
- 7 products (egg.duck, meat, offal, fat, bones, feathers, down)
- 3 feed types (starter, grower, layer - 20kg bags)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-27 19:40:55 +00:00
parent 34b2421604
commit 4579229734
12 changed files with 1456 additions and 2 deletions

30
tests/test_id_gen.py Normal file
View File

@@ -0,0 +1,30 @@
# ABOUTME: Tests for ULID generation utility.
# ABOUTME: Verifies that generated IDs are valid 26-character ULIDs and unique.
from animaltrack.id_gen import generate_id
class TestGenerateId:
"""Tests for the generate_id function."""
def test_returns_string(self):
"""generate_id returns a string."""
result = generate_id()
assert isinstance(result, str)
def test_returns_26_characters(self):
"""generate_id returns exactly 26 characters (ULID format)."""
result = generate_id()
assert len(result) == 26
def test_returns_unique_ids(self):
"""generate_id returns unique IDs on each call."""
ids = [generate_id() for _ in range(100)]
assert len(set(ids)) == 100
def test_ulid_is_uppercase_alphanumeric(self):
"""ULID contains only uppercase letters and digits (Crockford base32)."""
result = generate_id()
# Crockford base32 excludes I, L, O, U
valid_chars = set("0123456789ABCDEFGHJKMNPQRSTVWXYZ")
assert all(c in valid_chars for c in result)