feat: improve mirror/deletion for assets, logs, animal types

This commit is contained in:
Lance Edgar 2026-02-26 19:10:41 -06:00
parent 96ccf30e46
commit a5d7f89fcb
15 changed files with 70 additions and 21 deletions

View file

@ -196,7 +196,12 @@ class AssetMixin:
@declared_attr
def asset(cls):
return orm.relationship(Asset)
return orm.relationship(
Asset,
single_parent=True,
cascade="all, delete-orphan",
cascade_backrefs=False,
)
def __str__(self):
return self.asset_name or ""

View file

@ -165,7 +165,12 @@ class LogMixin:
@declared_attr
def log(cls):
return orm.relationship(Log)
return orm.relationship(
Log,
single_parent=True,
cascade="all, delete-orphan",
cascade_backrefs=False,
)
def __str__(self):
return self.message or ""

View file

@ -42,6 +42,8 @@ class AnimalTypeView(AssetTypeMasterView):
route_prefix = "animal_types"
url_prefix = "/animal-types"
farmos_entity_type = "taxonomy_term"
farmos_bundle = "animal_type"
farmos_refurl_path = "/admin/structure/taxonomy/manage/animal_type/overview"
grid_columns = [
@ -145,6 +147,7 @@ class AnimalAssetView(AssetMasterView):
url_prefix = "/assets/animal"
farmos_refurl_path = "/assets/animal"
farmos_bundle = "animal"
labels = {
"animal_type": "Species/Breed",

View file

@ -135,6 +135,8 @@ class AssetMasterView(WuttaFarmMasterView):
Base class for Asset master views
"""
farmos_entity_type = "asset"
sort_defaults = "asset_name"
filter_defaults = {
@ -276,22 +278,6 @@ class AssetMasterView(WuttaFarmMasterView):
model_class = self.get_model_class()
return model_class.__wutta_hint__["farmos_asset_type"]
def delete_instance(self, obj):
# save farmOS UUID if we need it
farmos_uuid = None
if self.app.is_farmos_mirror() and hasattr(obj, "farmos_uuid"):
farmos_uuid = obj.farmos_uuid
# delete per usual
super().delete_instance(obj)
# maybe delete from farmOS also
if farmos_uuid:
client = get_farmos_client_for_user(self.request)
asset_type = self.get_asset_type()
client.asset.delete(asset_type, farmos_uuid)
def get_farmos_url(self, asset):
return self.app.get_farmos_url(f"/asset/{asset.drupal_id}")

View file

@ -37,6 +37,7 @@ class GroupView(AssetMasterView):
url_prefix = "/assets/group"
farmos_refurl_path = "/assets/group"
farmos_bundle = "group"
grid_columns = [
"thumbnail",

View file

@ -139,6 +139,7 @@ class LandAssetView(AssetMasterView):
route_prefix = "land_assets"
url_prefix = "/assets/land"
farmos_bundle = "land"
farmos_refurl_path = "/assets/land"
grid_columns = [

View file

@ -166,6 +166,8 @@ class LogMasterView(WuttaFarmMasterView):
Base class for Asset master views
"""
farmos_entity_type = "log"
labels = {
"message": "Log Name",
"owners": "Owner",

View file

@ -36,6 +36,7 @@ class ActivityLogView(LogMasterView):
route_prefix = "logs_activity"
url_prefix = "/logs/activity"
farmos_bundle = "activity"
farmos_refurl_path = "/logs/activity"

View file

@ -36,6 +36,7 @@ class HarvestLogView(LogMasterView):
route_prefix = "logs_harvest"
url_prefix = "/logs/harvest"
farmos_bundle = "harvest"
farmos_refurl_path = "/logs/harvest"

View file

@ -36,6 +36,7 @@ class MedicalLogView(LogMasterView):
route_prefix = "logs_medical"
url_prefix = "/logs/medical"
farmos_bundle = "medical"
farmos_refurl_path = "/logs/medical"

View file

@ -36,6 +36,7 @@ class ObservationLogView(LogMasterView):
route_prefix = "logs_observation"
url_prefix = "/logs/observation"
farmos_bundle = "observation"
farmos_refurl_path = "/logs/observation"

View file

@ -27,7 +27,7 @@ from webhelpers2.html import tags
from wuttaweb.views import MasterView
from wuttafarm.web.util import use_farmos_style_grid_links
from wuttafarm.web.util import use_farmos_style_grid_links, get_farmos_client_for_user
class WuttaFarmMasterView(MasterView):
@ -36,6 +36,8 @@ class WuttaFarmMasterView(MasterView):
"""
farmos_refurl_path = None
farmos_entity_type = None
farmos_bundle = None
labels = {
"farmos_uuid": "farmOS UUID",
@ -104,6 +106,42 @@ class WuttaFarmMasterView(MasterView):
f.set_readonly("drupal_id")
def persist(self, obj, session=None):
# save per usual
super().persist(obj, session)
# maybe also sync change to farmOS
if self.app.is_farmos_mirror():
token = self.request.session.get("farmos.oauth2.token")
self.app.auto_sync_to_farmos(obj, token=token, require=False)
def get_farmos_entity_type(self):
if self.farmos_entity_type:
return self.farmos_entity_type
raise NotImplementedError(
f"must define {self.__class__.__name__}.farmos_entity_type"
)
def get_farmos_bundle(self):
if self.farmos_bundle:
return self.farmos_bundle
raise NotImplementedError(
f"must define {self.__class__.__name__}.farmos_bundle"
)
def delete_instance(self, obj):
# save farmOS UUID if we need it
farmos_uuid = None
if hasattr(obj, "farmos_uuid") and self.app.is_farmos_mirror():
farmos_uuid = obj.farmos_uuid
# delete per usual
super().delete_instance(obj)
# maybe delete from farmOS also
if farmos_uuid:
entity_type = self.get_farmos_entity_type()
bundle = self.get_farmos_bundle()
client = get_farmos_client_for_user(self.request)
client.resource.delete(entity_type, bundle, farmos_uuid)

View file

@ -41,6 +41,7 @@ class PlantTypeView(AssetTypeMasterView):
url_prefix = "/plant-types"
farmos_refurl_path = "/admin/structure/taxonomy/manage/plant_type/overview"
farmos_bundle = "plant"
grid_columns = [
"name",

View file

@ -138,6 +138,7 @@ class StructureAssetView(AssetMasterView):
route_prefix = "structure_assets"
url_prefix = "/asset/structures"
farmos_bundle = "structure"
farmos_refurl_path = "/assets/structure"
grid_columns = [

View file

@ -69,6 +69,8 @@ class UnitView(WuttaFarmMasterView):
route_prefix = "units"
url_prefix = "/units"
farmos_entity_type = "taxonomy_term"
farmos_bundle = "unit"
farmos_refurl_path = "/admin/structure/taxonomy/manage/unit/overview"
grid_columns = [