65 lines
2.2 KiB
Python
65 lines
2.2 KiB
Python
from __future__ import annotations
|
|
|
|
from django.db import transaction
|
|
|
|
from apps.jobs.services.geocoding import LocationMatchResult, resolve_cached_location
|
|
|
|
from .models import ProfileRevision, SearchProfile
|
|
|
|
|
|
@transaction.atomic
|
|
def resolve_profile_home_location(profile: SearchProfile) -> LocationMatchResult:
|
|
"""Resolve a user-entered postal code without exposing coordinate fields in the UI."""
|
|
query = profile.home_postal_code.strip()
|
|
result = (
|
|
resolve_cached_location(query) if query else LocationMatchResult(query=query, location=None)
|
|
)
|
|
location = result.location
|
|
profile.home_municipality = location.municipality or "" if location else ""
|
|
profile.home_latitude = location.point.latitude if location and location.point else None
|
|
profile.home_longitude = location.point.longitude if location and location.point else None
|
|
profile.save(
|
|
update_fields=[
|
|
"home_municipality",
|
|
"home_latitude",
|
|
"home_longitude",
|
|
"updated_at",
|
|
]
|
|
)
|
|
return result
|
|
|
|
|
|
@transaction.atomic
|
|
def save_profile_revision(profile: SearchProfile, *, reason: str) -> ProfileRevision:
|
|
latest = profile.revisions.order_by("-version").first()
|
|
next_version = (latest.version if latest else 0) + 1
|
|
if profile.version != next_version:
|
|
profile.version = next_version
|
|
profile.save(update_fields=["version", "updated_at"])
|
|
return ProfileRevision.objects.create(
|
|
profile=profile,
|
|
version=next_version,
|
|
snapshot=profile.snapshot(),
|
|
reason=reason,
|
|
)
|
|
|
|
|
|
@transaction.atomic
|
|
def apply_feedback_delta(
|
|
profile: SearchProfile,
|
|
feature: str,
|
|
delta: float,
|
|
*,
|
|
min_weight: float = 0.0,
|
|
max_weight: float = 40.0,
|
|
) -> SearchProfile:
|
|
if not profile.learning_enabled:
|
|
return profile
|
|
weights = dict(profile.weights)
|
|
current = float(weights.get(feature, 0.0))
|
|
weights[feature] = round(max(min_weight, min(max_weight, current + delta)), 2)
|
|
profile.weights = weights
|
|
profile.save(update_fields=["weights", "updated_at"])
|
|
save_profile_revision(profile, reason=f"feedback_delta:{feature}:{delta:+.2f}")
|
|
return profile
|