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 @declared_attr
def asset(cls): def asset(cls):
return orm.relationship(Asset) return orm.relationship(
Asset,
single_parent=True,
cascade="all, delete-orphan",
cascade_backrefs=False,
)
def __str__(self): def __str__(self):
return self.asset_name or "" return self.asset_name or ""

View file

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

View file

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

View file

@ -135,6 +135,8 @@ class AssetMasterView(WuttaFarmMasterView):
Base class for Asset master views Base class for Asset master views
""" """
farmos_entity_type = "asset"
sort_defaults = "asset_name" sort_defaults = "asset_name"
filter_defaults = { filter_defaults = {
@ -276,22 +278,6 @@ class AssetMasterView(WuttaFarmMasterView):
model_class = self.get_model_class() model_class = self.get_model_class()
return model_class.__wutta_hint__["farmos_asset_type"] 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): def get_farmos_url(self, asset):
return self.app.get_farmos_url(f"/asset/{asset.drupal_id}") return self.app.get_farmos_url(f"/asset/{asset.drupal_id}")

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -27,7 +27,7 @@ from webhelpers2.html import tags
from wuttaweb.views import MasterView 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): class WuttaFarmMasterView(MasterView):
@ -36,6 +36,8 @@ class WuttaFarmMasterView(MasterView):
""" """
farmos_refurl_path = None farmos_refurl_path = None
farmos_entity_type = None
farmos_bundle = None
labels = { labels = {
"farmos_uuid": "farmOS UUID", "farmos_uuid": "farmOS UUID",
@ -104,6 +106,42 @@ class WuttaFarmMasterView(MasterView):
f.set_readonly("drupal_id") f.set_readonly("drupal_id")
def persist(self, obj, session=None): def persist(self, obj, session=None):
# save per usual
super().persist(obj, session) super().persist(obj, session)
token = self.request.session.get("farmos.oauth2.token")
self.app.auto_sync_to_farmos(obj, token=token, require=False) # 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" url_prefix = "/plant-types"
farmos_refurl_path = "/admin/structure/taxonomy/manage/plant_type/overview" farmos_refurl_path = "/admin/structure/taxonomy/manage/plant_type/overview"
farmos_bundle = "plant"
grid_columns = [ grid_columns = [
"name", "name",

View file

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

View file

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