"""Link HQ Site rows to ActiveSite registry entries (Pengaturan view list).""" from __future__ import annotations from django.db import transaction from django.utils.text import slugify from apps.farms.models import Kandang, Site from apps.sync.models import ActiveSite def desired_hq_site_id(active_site: ActiveSite) -> str: """HQ Site PK should match the farm site slug when known.""" source = str(active_site.source_site_id or "").strip() if source: return source[:64] code = slugify(str(active_site.code or "").strip())[:64] if code: return code raise ValueError("ActiveSite needs source_site_id or code to create an HQ site.") @transaction.atomic def ensure_hq_site_for_active_site(active_site: ActiveSite) -> Site: """ Ensure the active-site registry entry has an HQ Site for farm visibility. Site.site_id matches ActiveSite.source_site_id (farm Site.site_id) when set. Prefers an existing linked site, then a site already keyed by that id, then an unlinked site owned by the registrar with a matching name (re-keyed if needed), otherwise creates a new Site. """ owner = active_site.managed_by if owner is None: raise ValueError("ActiveSite.managed_by is required to create an HQ site.") desired_id = desired_hq_site_id(active_site) site_name = (active_site.name or active_site.code or "Site")[:30] existing = Site.objects.filter(active_site=active_site).first() if existing is not None: if existing.pk == desired_id: return existing return _rekey_site(existing, desired_id=desired_id, site_name=site_name, owner=owner) by_pk = Site.objects.filter(pk=desired_id).first() if by_pk is not None: by_pk.active_site = active_site by_pk.user = owner if by_pk.site_name != site_name: by_pk.site_name = site_name by_pk.save(update_fields=["active_site", "user", "site_name", "updated_at"]) return by_pk orphan = ( Site.objects.filter( user=owner, active_site__isnull=True, site_name__iexact=site_name ) .order_by("pk") .first() ) if orphan is None and active_site.code: orphan = ( Site.objects.filter( user=owner, active_site__isnull=True, site_name__iexact=active_site.code ) .order_by("pk") .first() ) if orphan is not None: if orphan.pk == desired_id: orphan.active_site = active_site orphan.save(update_fields=["active_site", "updated_at"]) return orphan return _rekey_site( orphan, desired_id=desired_id, site_name=site_name, owner=owner, active_site=active_site, ) return Site.objects.create( site_id=desired_id, site_name=site_name, user=owner, active_site=active_site, ) def _rekey_site( old: Site, *, desired_id: str, site_name: str, owner, active_site: ActiveSite | None = None, ) -> Site: """Move an HQ site (and its kandangs) onto the farm slug primary key.""" link = active_site if active_site is not None else old.active_site new_site = Site.objects.create( site_id=desired_id, site_name=site_name or old.site_name, user=owner, active_site=None, ) Kandang.objects.filter(site=old).update(site=new_site) old_active = old.active_site old.delete() new_site.active_site = link or old_active new_site.save(update_fields=["active_site", "updated_at"]) return new_site