feat(reporting): Implement 'Report Mistake' feature with API and UI [2f388f42]

This commit is contained in:
2026-01-27 09:00:20 +00:00
parent fff89ff012
commit d67245c50a
6 changed files with 520 additions and 13 deletions

View File

@@ -17,7 +17,7 @@ setup_logging()
import logging
logger = logging.getLogger(__name__)
from .database import init_db, get_db, Company, Signal, EnrichmentData, RoboticsCategory, Contact, Industry, JobRoleMapping
from .database import init_db, get_db, Company, Signal, EnrichmentData, RoboticsCategory, Contact, Industry, JobRoleMapping, ReportedMistake
from .services.deduplication import Deduplicator
from .services.discovery import DiscoveryService
from .services.scraping import ScraperService
@@ -61,6 +61,14 @@ class AnalysisRequest(BaseModel):
class IndustryUpdateModel(BaseModel):
industry_ai: str
class ReportMistakeRequest(BaseModel):
field_name: str
wrong_value: Optional[str] = None
corrected_value: Optional[str] = None
source_url: Optional[str] = None
quote: Optional[str] = None
user_comment: Optional[str] = None
# --- Events ---
@app.on_event("startup")
def on_startup():
@@ -240,6 +248,47 @@ def list_industries(db: Session = Depends(get_db)):
def list_job_roles(db: Session = Depends(get_db)):
return db.query(JobRoleMapping).order_by(JobRoleMapping.pattern.asc()).all()
@app.get("/api/mistakes")
def list_reported_mistakes(
status: Optional[str] = Query(None),
skip: int = 0,
limit: int = 50,
db: Session = Depends(get_db)
):
query = db.query(ReportedMistake).options(joinedload(ReportedMistake.company))
if status:
query = query.filter(ReportedMistake.status == status.upper())
total = query.count()
items = query.order_by(ReportedMistake.created_at.desc()).offset(skip).limit(limit).all()
return {"total": total, "items": items}
class MistakeUpdateStatusRequest(BaseModel):
status: str # PENDING, APPROVED, REJECTED
@app.put("/api/mistakes/{mistake_id}")
def update_reported_mistake_status(
mistake_id: int,
request: MistakeUpdateStatusRequest,
db: Session = Depends(get_db)
):
mistake = db.query(ReportedMistake).filter(ReportedMistake.id == mistake_id).first()
if not mistake:
raise HTTPException(404, detail="Reported mistake not found")
if request.status.upper() not in ["PENDING", "APPROVED", "REJECTED"]:
raise HTTPException(400, detail="Invalid status. Must be PENDING, APPROVED, or REJECTED.")
mistake.status = request.status.upper()
mistake.updated_at = datetime.utcnow()
db.commit()
db.refresh(mistake)
logger.info(f"Updated status for mistake {mistake_id} to {mistake.status}")
return {"status": "success", "mistake": mistake}
@app.post("/api/enrich/discover")
def discover_company(req: AnalysisRequest, background_tasks: BackgroundTasks, db: Session = Depends(get_db)):
company = db.query(Company).filter(Company.id == req.company_id).first()
@@ -317,35 +366,115 @@ def override_website(company_id: int, url: str, db: Session = Depends(get_db)):
return {"status": "updated", "website": company.website}
@app.post("/api/companies/{company_id}/override/impressum")
def override_impressum(company_id: int, url: str, background_tasks: BackgroundTasks, db: Session = Depends(get_db)):
company = db.query(Company).filter(Company.id == company_id).first()
if not company:
raise HTTPException(404, detail="Company not found")
# Create or update manual impressum lock
existing = db.query(EnrichmentData).filter(
EnrichmentData.company_id == company_id,
EnrichmentData.source_type == "impressum_override"
).first()
if not existing:
db.add(EnrichmentData(
company_id=company_id,
source_type="impressum_override",
content={"url": url},
is_locked=True
))
else:
existing.content = {"url": url}
existing.is_locked = True
db.commit()
return {"status": "updated"}
@app.post("/api/companies/{company_id}/report-mistake")
def report_company_mistake(
company_id: int,
request: ReportMistakeRequest,
db: Session = Depends(get_db)
):
company = db.query(Company).filter(Company.id == company_id).first()
if not company:
raise HTTPException(404, detail="Company not found")
new_mistake = ReportedMistake(
company_id=company_id,
field_name=request.field_name,
wrong_value=request.wrong_value,
corrected_value=request.corrected_value,
source_url=request.source_url,
quote=request.quote,
user_comment=request.user_comment
)
db.add(new_mistake)
db.commit()
db.refresh(new_mistake)
logger.info(f"Reported mistake for company {company_id}: {request.field_name} -> {request.corrected_value}")
return {"status": "success", "mistake_id": new_mistake.id}
def run_wikipedia_reevaluation_task(company_id: int):
from .database import SessionLocal
db = SessionLocal()
try:
company = db.query(Company).filter(Company.id == company_id).first()