from __future__ import annotations import re from functools import cached_property from django.apps import AppConfig class PlantConfig(AppConfig): default_auto_field = "django.db.models.BigAutoField" name = "plant" verbose_name = "Plant" @cached_property def plant_aliases(self) -> dict[str, str]: return { "tomato": "گوجه‌فرنگی", "cucumber": "خیار", "pepper": "فلفل دلمه‌ای", "bell pepper": "فلفل دلمه‌ای", "carrot": "هویج", "lettuce": "کاهو", "potato": "سیب‌زمینی", "onion": "پیاز", } @cached_property def growth_stage_aliases(self) -> dict[str, str]: return { "initial": "initial", "seedling": "initial", "establishment": "initial", "جوانه زنی": "initial", "جوانه‌زنی": "initial", "نشا": "initial", "استقرار": "initial", "vegetative": "vegetative", "growth": "vegetative", "رویشی": "vegetative", "رشد رویشی": "vegetative", "flowering": "flowering", "anthesis": "flowering", "گلدهی": "flowering", "گل دهی": "flowering", "fruiting": "fruiting", "harvest": "fruiting", "ripening": "fruiting", "میوه دهی": "fruiting", "میوه‌دهی": "fruiting", "برداشت": "fruiting", "maturity": "maturity", "رسیدگی": "maturity", "بلوغ": "maturity", } def _normalize_lookup_value(self, value: str | None) -> str: text = (value or "").strip().lower() if not text: return "" translation_table = str.maketrans( { "ي": "ی", "ك": "ک", "ة": "ه", "أ": "ا", "إ": "ا", "ؤ": "و", "ۀ": "ه", "‌": " ", "-": " ", "_": " ", } ) text = text.translate(translation_table) text = re.sub(r"\s+", " ", text) return text.strip() def resolve_growth_stage(self, growth_stage: str | None) -> str | None: value = (growth_stage or "").strip() if not value: return value normalized = self._normalize_lookup_value(value) return self.growth_stage_aliases.get(normalized, value) def resolve_plant_name(self, plant_name: str | None) -> str | None: from farm_data.models import PlantCatalogSnapshot value = (plant_name or "").strip() if not value: return value plant = ( PlantCatalogSnapshot.objects.filter(name=value).first() or PlantCatalogSnapshot.objects.filter(name__iexact=value).first() ) if plant is not None: return plant.name normalized = self._normalize_lookup_value(value) alias_target = self.plant_aliases.get(normalized) if alias_target: aliased_plant = PlantCatalogSnapshot.objects.filter(name=alias_target).first() if aliased_plant is not None: return aliased_plant.name for plant in PlantCatalogSnapshot.objects.only("name").iterator(): if self._normalize_lookup_value(plant.name) == normalized: return plant.name return value