StocKing / return_lifecycle.py
adoomy's picture
Add automatic shareholder return estimates and numeric yield sorting
992d9b8
Raw History Blame Contribute Delete
1.87 kB
"""Automatic application and reversible exclusion of collected return evidence."""
import json
from datetime import datetime
from sqlalchemy import update
from models import ReturnDocument, ReturnAudit
from shareholder_returns import load_documents
def automatic_status(document):
if document.get("error"):
return "reference"
if document.get("is_withdrawal"):
return "active" if document.get("supersedes_id") else "reference"
events = document.get("events") or []
policies = document.get("policies") or []
usable_event = any(e.get("scope") == "common" and e.get("amount") is not None for e in events)
usable_policy = any(p.get("scope") == "common" and (p.get("amount") is not None or p.get("ratio") is not None or p.get("kind") == "none") for p in policies)
return "active" if usable_event or usable_policy else "reference"
def apply_pending_documents(db):
"""Upgrade existing candidates once, in bulk; never override a user's exclusion."""
documents = [d for d in load_documents(db) if d["status"] == "pending"]
now = datetime.utcnow()
groups = {"active": [], "reference": []}
for before in documents:
status = automatic_status(before)
groups[status].append(before["id"])
after = {**before, "status": status, "updated_at": now.isoformat()}
db.add(ReturnAudit(document_id=before["id"], action="auto_apply" if status == "active" else "reference",
snapshot=json.dumps({"before": before, "after": after}, ensure_ascii=False)))
for status, ids in groups.items():
if ids:
db.execute(update(ReturnDocument).where(ReturnDocument.id.in_(ids), ReturnDocument.status == "pending").values(status=status, updated_at=now))
if documents:
db.commit()
return {status: len(ids) for status, ids in groups.items()}