Cleanup tool: "mark deceased by a child's birth year" rule
Adds a preview/apply rule to the Cleanup tool for parents who have NO birth date
of their own (so the existing born-on-or-before rule can't reach them) but who
have a child born long ago — they're necessarily deceased. This is the gap that
left ~56 parents in the Paul tree as "unknown".
- cleanup_service.preview_deceased_by_child(year): parents of any child born
on/before the cutoff, excluding already-deceased; returns child_birth_year.
- GET /trees/{id}/cleanup/deceased-by-child?born_on_or_before=1900. Apply reuses
the existing POST .../cleanup/deceased (same audited mark-deceased path).
- Frontend: a new card in the Cleanup tool (year input → preview → select →
apply), preview-first like the rest of the tool.
Test covers preview (finds the no-birthdate parent of a pre-cutoff child,
excludes modern-child parents), child_birth_year, apply, and re-preview drop.
Suite 106 passing.
Signed-off-by: Justin Paul <justin@jpaul.me>
This commit is contained in:
@@ -51,6 +51,53 @@ async def test_deceased_preview_and_apply(client):
|
||||
assert old not in [r["person_id"] for r in prev2]
|
||||
|
||||
|
||||
async def test_deceased_by_child_preview_and_apply(client):
|
||||
h, tid = await _tree(client, "cl-decchild@example.com")
|
||||
# Parent with NO birth date (the gap the birth-year rule can't reach).
|
||||
parent = await _person(client, h, tid, "Gesche", "Frerking")
|
||||
child = await _person(client, h, tid, "Kindt", "Frerking")
|
||||
await _birth(client, h, tid, child, 1880) # child born before the cutoff
|
||||
await client.post(
|
||||
f"/api/v1/trees/{tid}/relationships",
|
||||
json={"type": "parent_child", "person_from_id": parent, "person_to_id": child},
|
||||
headers=h,
|
||||
)
|
||||
# A parent of a modern child must NOT be flagged.
|
||||
p_modern = await _person(client, h, tid, "Modern", "Parent")
|
||||
c_modern = await _person(client, h, tid, "Kid", "Parent")
|
||||
await _birth(client, h, tid, c_modern, 1990)
|
||||
await client.post(
|
||||
f"/api/v1/trees/{tid}/relationships",
|
||||
json={"type": "parent_child", "person_from_id": p_modern, "person_to_id": c_modern},
|
||||
headers=h,
|
||||
)
|
||||
|
||||
prev = (
|
||||
await client.get(
|
||||
f"/api/v1/trees/{tid}/cleanup/deceased-by-child?born_on_or_before=1900", headers=h
|
||||
)
|
||||
).json()
|
||||
ids = [r["person_id"] for r in prev]
|
||||
assert parent in ids and p_modern not in ids
|
||||
assert next(r for r in prev if r["person_id"] == parent)["child_birth_year"] == 1880
|
||||
|
||||
# Apply through the shared deceased endpoint.
|
||||
r = await client.post(
|
||||
f"/api/v1/trees/{tid}/cleanup/deceased", json={"person_ids": [parent]}, headers=h
|
||||
)
|
||||
assert r.status_code == 200 and r.json()["updated"] == 1
|
||||
assert (
|
||||
await client.get(f"/api/v1/trees/{tid}/persons/{parent}", headers=h)
|
||||
).json()["is_living"] is False
|
||||
# Re-preview drops the now-deceased parent.
|
||||
prev2 = (
|
||||
await client.get(
|
||||
f"/api/v1/trees/{tid}/cleanup/deceased-by-child?born_on_or_before=1900", headers=h
|
||||
)
|
||||
).json()
|
||||
assert parent not in [r["person_id"] for r in prev2]
|
||||
|
||||
|
||||
async def test_gender_from_spouse_preview_and_apply(client):
|
||||
h, tid = await _tree(client, "cl-spouse@example.com")
|
||||
husband = (
|
||||
|
||||
Reference in New Issue
Block a user