diff --git a/CHANGELOG.md b/CHANGELOG.md
index f6b8703..b5241ed 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,30 +5,6 @@ All notable changes to WuttaFarm will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
-## v0.3.0 (2026-02-13)
-
-### Feat
-
-- add native table for Activity Logs; import from farmOS API
-- add native table for Groups; import from farmOS API
-- add native table for Animals; import from farmOS API
-- add native table for Structures; import from farmOS API
-- add native table for Land Assets; import from farmOS API
-- add native table for Log Types; import from farmOS API
-- add native table for Structure Types; import from farmOS API
-- add native table for Land Types; import from farmOS API
-- add native table for Asset Types; import from farmOS API
-- add extension table for Users; import from farmOS API
-- add native table for Animal Types; import from farmOS API
-- add "See raw JSON data" button for farmOS API views
-
-### Fix
-
-- always make 'farmos' system user in app setup
-- avoid error for Create User form
-- add more perms to Site Admin role in app setup
-- rename `drupal_internal_id` => `drupal_id`
-
## v0.2.3 (2026-02-08)
### Fix
diff --git a/docs/api/wuttafarm.cli.base.rst b/docs/api/wuttafarm.cli.base.rst
deleted file mode 100644
index 19afd5c..0000000
--- a/docs/api/wuttafarm.cli.base.rst
+++ /dev/null
@@ -1,6 +0,0 @@
-
-``wuttafarm.cli.base``
-======================
-
-.. automodule:: wuttafarm.cli.base
- :members:
diff --git a/docs/api/wuttafarm.cli.import_farmos.rst b/docs/api/wuttafarm.cli.import_farmos.rst
deleted file mode 100644
index 12a6d03..0000000
--- a/docs/api/wuttafarm.cli.import_farmos.rst
+++ /dev/null
@@ -1,6 +0,0 @@
-
-``wuttafarm.cli.import_farmos``
-===============================
-
-.. automodule:: wuttafarm.cli.import_farmos
- :members:
diff --git a/docs/api/wuttafarm.cli.install.rst b/docs/api/wuttafarm.cli.install.rst
deleted file mode 100644
index e825989..0000000
--- a/docs/api/wuttafarm.cli.install.rst
+++ /dev/null
@@ -1,6 +0,0 @@
-
-``wuttafarm.cli.install``
-=========================
-
-.. automodule:: wuttafarm.cli.install
- :members:
diff --git a/docs/api/wuttafarm.importing.farmos.rst b/docs/api/wuttafarm.importing.farmos.rst
deleted file mode 100644
index b6e00b4..0000000
--- a/docs/api/wuttafarm.importing.farmos.rst
+++ /dev/null
@@ -1,6 +0,0 @@
-
-``wuttafarm.importing.farmos``
-==============================
-
-.. automodule:: wuttafarm.importing.farmos
- :members:
diff --git a/docs/api/wuttafarm.importing.rst b/docs/api/wuttafarm.importing.rst
deleted file mode 100644
index 5c331b9..0000000
--- a/docs/api/wuttafarm.importing.rst
+++ /dev/null
@@ -1,6 +0,0 @@
-
-``wuttafarm.importing``
-=======================
-
-.. automodule:: wuttafarm.importing
- :members:
diff --git a/docs/conf.py b/docs/conf.py
index f3fd9e2..3caa6e3 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -21,7 +21,6 @@ extensions = [
"sphinx.ext.intersphinx",
"sphinx.ext.viewcode",
"sphinx.ext.todo",
- "sphinxcontrib.programoutput",
]
templates_path = ["_templates"]
diff --git a/docs/index.rst b/docs/index.rst
index be04bee..4c7887b 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -8,6 +8,9 @@ and extend `farmOS`_.
.. _WuttaWeb: https://wuttaproject.org
.. _farmOS: https://farmos.org
+.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
+ :target: https://github.com/psf/black
+
It is just an experiment so far; the ideas I hope to play with
include:
@@ -16,9 +19,6 @@ include:
- possibly add more schema / extra features
- possibly sync data back to farmOS
-.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
- :target: https://github.com/psf/black
-
.. toctree::
:maxdepth: 2
@@ -27,7 +27,6 @@ include:
narr/install
narr/auth
narr/features
- narr/cli
.. toctree::
@@ -38,16 +37,11 @@ include:
api/wuttafarm.app
api/wuttafarm.auth
api/wuttafarm.cli
- api/wuttafarm.cli.base
- api/wuttafarm.cli.import_farmos
- api/wuttafarm.cli.install
api/wuttafarm.config
api/wuttafarm.db
api/wuttafarm.db.model
api/wuttafarm.farmos
api/wuttafarm.farmos.handler
- api/wuttafarm.importing
- api/wuttafarm.importing.farmos
api/wuttafarm.install
api/wuttafarm.web
api/wuttafarm.web.app
diff --git a/docs/narr/auth.rst b/docs/narr/auth.rst
index 536f3d0..67a63fa 100644
--- a/docs/narr/auth.rst
+++ b/docs/narr/auth.rst
@@ -36,13 +36,7 @@ browse farmOS data within the WuttaFarm views.
If you login to WuttaFarm directly with username/password, then
your user session will not have a farmOS access token and so the
- farmOS data views in WuttaFarm will not work (i.e. anything under
- the **farmOS** menu).
-
- (However this does not affect the "native" data views for
- WuttaFarm. Users can see data which was already imported from
- farmOS without an access token - if they have appropriate
- permissions in WuttaFarm.)
+ farmOS data views in WuttaFarm will not work.
On the login page, click the "Login via farmOS / OAuth2" button. This
will initiate the OAuth2 workflow, at which point you may be asked to
diff --git a/docs/narr/cli.rst b/docs/narr/cli.rst
deleted file mode 100644
index 70b7c1e..0000000
--- a/docs/narr/cli.rst
+++ /dev/null
@@ -1,39 +0,0 @@
-
-========================
- Command Line Interface
-========================
-
-WuttaFarm ships with the following commands.
-
-For more general info about CLI see
-:doc:`wuttjamaican:narr/cli/index`.
-
-
-.. _wuttafarm-install:
-
-``wuttafarm install``
----------------------
-
-Run the WuttaFarm app installer.
-
-This will create the :term:`app dir` and initial config files, and
-create the schema within the :term:`app database`.
-
-Defined in: :mod:`wuttafarm.cli.install`
-
-.. program-output:: wuttafarm install --help
-
-
-.. _wuttafarm-import-farmos:
-
-``wuttafarm import-farmos``
----------------------------
-
-Import data from the farmOS API into the WuttaFarm :term:`app
-database`.
-
-Defined in: :mod:`wuttafarm.cli.import_farmos`
-
-.. program-output:: wuttafarm import-farmos --help
-
-
diff --git a/docs/narr/features.rst b/docs/narr/features.rst
index 60a9120..00e435b 100644
--- a/docs/narr/features.rst
+++ b/docs/narr/features.rst
@@ -14,10 +14,6 @@ Here is the list of features currently supported:
* performance isn't bad, but data is not very "complete"
* more data could be fetched, but not sure this is the best way..?
-* import some data from farmOS
- * limited data is imported from farmOS API into native app tables
- * this data is exposed in views, similar to direct farmOS views (above)
-
Screenshots
-----------
diff --git a/docs/narr/install.rst b/docs/narr/install.rst
index 1147a6d..fdb9958 100644
--- a/docs/narr/install.rst
+++ b/docs/narr/install.rst
@@ -60,93 +60,3 @@ are encouraged to enable it anyway.
When the installer completes it will output a command you can then use
to run the web app. Do that and you can then view the app in a
browser at http://localhost:9080
-
-
-OAuth2 Setup
-------------
-
-At this point the web app should be ready for OAuth2 login; however
-the OAuth2 provider in farmOS needs some more config before it will
-work.
-
-WuttaFarm uses the default ``farm`` consumer, so the only thing you
-should have to do here is edit that to add your redirect URL. This
-will vary based on your WuttaFarm site name, e.g.
-
-.. code-block:: none
-
- https://wuttafarm.example.com/farmos/oauth/callback
-
-With that in place you should be able to login via OAuth2; see also
-:doc:`/narr/auth`.
-
-However while you're there, you should also do some setup for the sake
-of the farmOS → WuttaFarm data import. This import will also use the
-farmOS API and therefore also needs an oauth2 access token; however it
-uses the Client Credentials workflow instead of the Authorization Code
-workflow. Therefore you must create a new *user* and a new OAuth2
-*consumer* for it.
-
-First add a new user in farmOS, named ``wuttafarm``. It should
-probably be given the Manager role, since WuttaFarm will eventually
-also support "exporting" data back to farmOS.
-
-Then add a new OAuth2 consumer (aka. client) with these attributes:
-
-* **Label:** WuttaFarm
-* **Client ID:** wuttafarm
-* **New Secret:** (put something in here, to be used as client secret)
-* **Grant Types:** Client Credentials, Refresh Token (maybe more?)
-* **User:** wuttafarm
-* **3rd Party?** yes
-* **Confidential?** yes
-* **Access Token Expiration Time:** maybe set to 3600? or maybe 300
- default is okay?
-* **Allowed Origins:** put your oauth callback URL here (same as for
- default ``farm`` consumer)
-
-WuttaFarm also needs to know the client secret for sake of running the
-import; so add this to your ``app/wutta.conf`` file. Of course
-replace the value with whatever client secret you gave the new
-consumer:
-
-.. code-block:: ini
-
- [farmos.oauth2]
- importing.client_secret = you_cant_guess_me
-
-
-Import Data from farmOS
------------------------
-
-You must have done all the OAuth2 setup (previous section) before the
-import will work.
-
-But now that you did all that, importing should be quick and easy.
-
-The very first import will be limited and "special" to account for any
-users which were already created in WuttaFarm. This command will
-ensure WuttaFarm gets *all* user accounts and each is appropriately
-mapped to the farmOS account:
-
-.. code-block:: sh
-
- ./venv/bin/wuttafarm --runas farmos import-farmos User --key username
-
-Note also the ``--runas farmos`` arg which helps the WuttaFarm data
-versioning know "who" is responsible for the changes. We use a
-dedicated ``farmos`` user account in WuttaFarm, to represent the
-farmOS system as a whole.
-
-From now on you can run the "full" import normally:
-
-.. code-block:: sh
-
- ./venv/bin/wuttafarm --runas farmos import-farmos
-
-And it can sometimes be helpful to "double-check" in order to make
-sure all data is fully synced:
-
-.. code-block:: sh
-
- ./venv/bin/wuttafarm --runas farmos import-farmos --delete --dry-run -W
diff --git a/pyproject.toml b/pyproject.toml
index f8fc499..fbc8df2 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -5,7 +5,7 @@ build-backend = "hatchling.build"
[project]
name = "WuttaFarm"
-version = "0.3.0"
+version = "0.2.3"
description = "Web app to integrate with and extend farmOS"
readme = "README.md"
authors = [
@@ -33,13 +33,12 @@ dependencies = [
"psycopg2",
"pyramid_exclog",
"uvicorn[standard]",
- "WuttaSync",
"WuttaWeb[continuum]>=0.27.4",
]
[project.optional-dependencies]
-docs = ["Sphinx", "furo", "sphinxcontrib-programoutput"]
+docs = ["Sphinx", "furo"]
[project.scripts]
@@ -48,18 +47,12 @@ docs = ["Sphinx", "furo", "sphinxcontrib-programoutput"]
[project.entry-points."paste.app_factory"]
"main" = "wuttafarm.web.app:main"
-[project.entry-points."wutta.app.providers"]
-wuttafarm = "wuttafarm.app:WuttaFarmAppProvider"
-
[project.entry-points."wutta.config.extensions"]
"wuttafarm" = "wuttafarm.config:WuttaFarmConfig"
[project.entry-points."wutta.web.menus"]
"wuttafarm" = "wuttafarm.web.menus:WuttaFarmMenuHandler"
-[project.entry-points."wuttasync.importing"]
-"import.to_wuttafarm.from_farmos" = "wuttafarm.importing.farmos:FromFarmOSToWuttaFarm"
-
[project.urls]
Homepage = "https://forgejo.wuttaproject.org/wutta/wuttafarm"
diff --git a/src/wuttafarm/app.py b/src/wuttafarm/app.py
index 72dd675..26c6ef8 100644
--- a/src/wuttafarm/app.py
+++ b/src/wuttafarm/app.py
@@ -64,11 +64,3 @@ class WuttaFarmAppHandler(base.AppHandler):
"""
handler = self.get_farmos_handler()
return handler.get_farmos_client(*args, **kwargs)
-
-
-class WuttaFarmAppProvider(base.AppProvider):
- """
- The :term:`app provider` for WuttaFarm.
- """
-
- email_modules = ["wuttafarm.emails"]
diff --git a/src/wuttafarm/cli/install.py b/src/wuttafarm/cli.py
similarity index 89%
rename from src/wuttafarm/cli/install.py
rename to src/wuttafarm/cli.py
index c82dab2..2f377a3 100644
--- a/src/wuttafarm/cli/install.py
+++ b/src/wuttafarm/cli.py
@@ -25,7 +25,12 @@ WuttaFarm CLI
import typer
-from wuttafarm.cli import wuttafarm_typer
+from wuttjamaican.cli import make_typer
+
+
+wuttafarm_typer = make_typer(
+ name="wuttafarm", help="WuttaFarm -- Web app to integrate with and extend farmOS"
+)
@wuttafarm_typer.command()
diff --git a/src/wuttafarm/cli/__init__.py b/src/wuttafarm/cli/__init__.py
deleted file mode 100644
index 7f6c2bb..0000000
--- a/src/wuttafarm/cli/__init__.py
+++ /dev/null
@@ -1,30 +0,0 @@
-# -*- coding: utf-8; -*-
-################################################################################
-#
-# WuttaFarm --Web app to integrate with and extend farmOS
-# Copyright © 2026 Lance Edgar
-#
-# This file is part of WuttaFarm.
-#
-# WuttaFarm is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-#
-# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# WuttaFarm. If not, see .
-#
-################################################################################
-"""
-WuttaFarm CLI
-"""
-
-from .base import wuttafarm_typer
-
-# nb. must bring in all modules for discovery to work
-from . import import_farmos
-from . import install
diff --git a/src/wuttafarm/cli/base.py b/src/wuttafarm/cli/base.py
deleted file mode 100644
index de16ead..0000000
--- a/src/wuttafarm/cli/base.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# -*- coding: utf-8; -*-
-################################################################################
-#
-# WuttaFarm --Web app to integrate with and extend farmOS
-# Copyright © 2026 Lance Edgar
-#
-# This file is part of WuttaFarm.
-#
-# WuttaFarm is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-#
-# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# WuttaFarm. If not, see .
-#
-################################################################################
-"""
-WuttaFarm CLI - base Typer instance
-"""
-
-from wuttjamaican.cli import make_typer
-
-
-wuttafarm_typer = make_typer(
- name="wuttafarm", help="WuttaFarm -- Web app to integrate with and extend farmOS"
-)
diff --git a/src/wuttafarm/cli/import_farmos.py b/src/wuttafarm/cli/import_farmos.py
deleted file mode 100644
index 4343d43..0000000
--- a/src/wuttafarm/cli/import_farmos.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# -*- coding: utf-8; -*-
-################################################################################
-#
-# WuttaFarm --Web app to integrate with and extend farmOS
-# Copyright © 2026 Lance Edgar
-#
-# This file is part of WuttaFarm.
-#
-# WuttaFarm is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-#
-# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# WuttaFarm. If not, see .
-#
-################################################################################
-"""
-See also: :ref:`wuttafarm-import-farmos`
-"""
-
-import typer
-
-from wuttasync.cli import import_command, ImportCommandHandler
-
-from wuttafarm.cli import wuttafarm_typer
-
-
-@wuttafarm_typer.command()
-@import_command
-def import_farmos(ctx: typer.Context, **kwargs):
- """
- Import data from farmOS API to WuttaFarm
- """
- config = ctx.parent.wutta_config
- handler = ImportCommandHandler(config, key="import.to_wuttafarm.from_farmos")
- handler.run(ctx)
diff --git a/src/wuttafarm/db/alembic/versions/1b2d3224e5dc_add_animals.py b/src/wuttafarm/db/alembic/versions/1b2d3224e5dc_add_animals.py
deleted file mode 100644
index 78400ac..0000000
--- a/src/wuttafarm/db/alembic/versions/1b2d3224e5dc_add_animals.py
+++ /dev/null
@@ -1,127 +0,0 @@
-"""add Animals
-
-Revision ID: 1b2d3224e5dc
-Revises: 4dbba8aeb1e5
-Create Date: 2026-02-13 11:55:19.564221
-
-"""
-
-from typing import Sequence, Union
-
-from alembic import op
-import sqlalchemy as sa
-import wuttjamaican.db.util
-
-
-# revision identifiers, used by Alembic.
-revision: str = "1b2d3224e5dc"
-down_revision: Union[str, None] = "4dbba8aeb1e5"
-branch_labels: Union[str, Sequence[str], None] = None
-depends_on: Union[str, Sequence[str], None] = None
-
-
-def upgrade() -> None:
-
- # animal
- op.create_table(
- "animal",
- sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
- sa.Column("name", sa.String(length=100), nullable=False),
- sa.Column("animal_type_uuid", wuttjamaican.db.util.UUID(), nullable=False),
- sa.Column("birthdate", sa.DateTime(), nullable=True),
- sa.Column("sex", sa.String(length=1), nullable=True),
- sa.Column("is_sterile", sa.Boolean(), nullable=True),
- sa.Column("active", sa.Boolean(), nullable=False),
- sa.Column("notes", sa.Text(), nullable=True),
- sa.Column("image_url", sa.String(length=255), nullable=True),
- sa.Column("farmos_uuid", wuttjamaican.db.util.UUID(), nullable=True),
- sa.Column("drupal_id", sa.Integer(), nullable=True),
- sa.ForeignKeyConstraint(
- ["animal_type_uuid"],
- ["animal_type.uuid"],
- name=op.f("fk_animal_animal_type_uuid_animal_type"),
- ),
- sa.PrimaryKeyConstraint("uuid", name=op.f("pk_animal")),
- sa.UniqueConstraint("drupal_id", name=op.f("uq_animal_drupal_id")),
- sa.UniqueConstraint("farmos_uuid", name=op.f("uq_animal_farmos_uuid")),
- )
- op.create_table(
- "animal_version",
- sa.Column(
- "uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
- ),
- sa.Column("name", sa.String(length=100), autoincrement=False, nullable=True),
- sa.Column(
- "animal_type_uuid",
- wuttjamaican.db.util.UUID(),
- autoincrement=False,
- nullable=True,
- ),
- sa.Column("birthdate", sa.DateTime(), autoincrement=False, nullable=True),
- sa.Column("sex", sa.String(length=1), autoincrement=False, nullable=True),
- sa.Column("is_sterile", sa.Boolean(), autoincrement=False, nullable=True),
- sa.Column("active", sa.Boolean(), autoincrement=False, nullable=True),
- sa.Column("notes", sa.Text(), autoincrement=False, nullable=True),
- sa.Column(
- "image_url", sa.String(length=255), autoincrement=False, nullable=True
- ),
- sa.Column(
- "farmos_uuid",
- wuttjamaican.db.util.UUID(),
- autoincrement=False,
- nullable=True,
- ),
- sa.Column("drupal_id", sa.Integer(), autoincrement=False, nullable=True),
- sa.Column(
- "transaction_id", sa.BigInteger(), autoincrement=False, nullable=False
- ),
- sa.Column("end_transaction_id", sa.BigInteger(), nullable=True),
- sa.Column("operation_type", sa.SmallInteger(), nullable=False),
- sa.PrimaryKeyConstraint(
- "uuid", "transaction_id", name=op.f("pk_animal_version")
- ),
- )
- op.create_index(
- op.f("ix_animal_version_end_transaction_id"),
- "animal_version",
- ["end_transaction_id"],
- unique=False,
- )
- op.create_index(
- op.f("ix_animal_version_operation_type"),
- "animal_version",
- ["operation_type"],
- unique=False,
- )
- op.create_index(
- "ix_animal_version_pk_transaction_id",
- "animal_version",
- ["uuid", sa.literal_column("transaction_id DESC")],
- unique=False,
- )
- op.create_index(
- "ix_animal_version_pk_validity",
- "animal_version",
- ["uuid", "transaction_id", "end_transaction_id"],
- unique=False,
- )
- op.create_index(
- op.f("ix_animal_version_transaction_id"),
- "animal_version",
- ["transaction_id"],
- unique=False,
- )
-
-
-def downgrade() -> None:
-
- # animal
- op.drop_index(op.f("ix_animal_version_transaction_id"), table_name="animal_version")
- op.drop_index("ix_animal_version_pk_validity", table_name="animal_version")
- op.drop_index("ix_animal_version_pk_transaction_id", table_name="animal_version")
- op.drop_index(op.f("ix_animal_version_operation_type"), table_name="animal_version")
- op.drop_index(
- op.f("ix_animal_version_end_transaction_id"), table_name="animal_version"
- )
- op.drop_table("animal_version")
- op.drop_table("animal")
diff --git a/src/wuttafarm/db/alembic/versions/2b6385d0fa17_add_animal_types.py b/src/wuttafarm/db/alembic/versions/2b6385d0fa17_add_animal_types.py
deleted file mode 100644
index 4e1481f..0000000
--- a/src/wuttafarm/db/alembic/versions/2b6385d0fa17_add_animal_types.py
+++ /dev/null
@@ -1,116 +0,0 @@
-"""add Animal Types
-
-Revision ID: 2b6385d0fa17
-Revises:
-Create Date: 2026-02-08 14:55:42.236918
-
-"""
-
-from typing import Sequence, Union
-
-from alembic import op
-import sqlalchemy as sa
-import wuttjamaican.db.util
-
-
-# revision identifiers, used by Alembic.
-revision: str = "2b6385d0fa17"
-down_revision: Union[str, None] = None
-branch_labels: Union[str, Sequence[str], None] = ("wuttafarm",)
-depends_on: Union[str, Sequence[str], None] = None
-
-
-def upgrade() -> None:
-
- # animal_type
- op.create_table(
- "animal_type",
- sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
- sa.Column("name", sa.String(length=100), nullable=False),
- sa.Column("description", sa.String(length=255), nullable=True),
- sa.Column("changed", sa.DateTime(), nullable=True),
- sa.Column("farmos_uuid", wuttjamaican.db.util.UUID(), nullable=True),
- sa.Column("drupal_id", sa.Integer(), nullable=True),
- sa.PrimaryKeyConstraint("uuid", name=op.f("pk_animal_type")),
- sa.UniqueConstraint("drupal_id", name=op.f("uq_animal_type_drupal_id")),
- sa.UniqueConstraint("farmos_uuid", name=op.f("uq_animal_type_farmos_uuid")),
- sa.UniqueConstraint("name", name=op.f("uq_animal_type_name")),
- )
- op.create_table(
- "animal_type_version",
- sa.Column(
- "uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
- ),
- sa.Column("name", sa.String(length=100), autoincrement=False, nullable=True),
- sa.Column(
- "description", sa.String(length=255), autoincrement=False, nullable=True
- ),
- sa.Column(
- "farmos_uuid",
- wuttjamaican.db.util.UUID(),
- autoincrement=False,
- nullable=True,
- ),
- sa.Column("drupal_id", sa.Integer(), autoincrement=False, nullable=True),
- sa.Column(
- "transaction_id", sa.BigInteger(), autoincrement=False, nullable=False
- ),
- sa.Column("end_transaction_id", sa.BigInteger(), nullable=True),
- sa.Column("operation_type", sa.SmallInteger(), nullable=False),
- sa.PrimaryKeyConstraint(
- "uuid", "transaction_id", name=op.f("pk_animal_type_version")
- ),
- )
- op.create_index(
- op.f("ix_animal_type_version_end_transaction_id"),
- "animal_type_version",
- ["end_transaction_id"],
- unique=False,
- )
- op.create_index(
- op.f("ix_animal_type_version_operation_type"),
- "animal_type_version",
- ["operation_type"],
- unique=False,
- )
- op.create_index(
- "ix_animal_type_version_pk_transaction_id",
- "animal_type_version",
- ["uuid", sa.literal_column("transaction_id DESC")],
- unique=False,
- )
- op.create_index(
- "ix_animal_type_version_pk_validity",
- "animal_type_version",
- ["uuid", "transaction_id", "end_transaction_id"],
- unique=False,
- )
- op.create_index(
- op.f("ix_animal_type_version_transaction_id"),
- "animal_type_version",
- ["transaction_id"],
- unique=False,
- )
-
-
-def downgrade() -> None:
-
- # animal_type
- op.drop_index(
- op.f("ix_animal_type_version_transaction_id"), table_name="animal_type_version"
- )
- op.drop_index(
- "ix_animal_type_version_pk_validity", table_name="animal_type_version"
- )
- op.drop_index(
- "ix_animal_type_version_pk_transaction_id", table_name="animal_type_version"
- )
- op.drop_index(
- op.f("ix_animal_type_version_operation_type"), table_name="animal_type_version"
- )
- op.drop_index(
- op.f("ix_animal_type_version_end_transaction_id"),
- table_name="animal_type_version",
- )
- op.drop_table("animal_type_version")
- op.drop_table("animal_type")
diff --git a/src/wuttafarm/db/alembic/versions/3e2ef02bf264_add_activity_logs.py b/src/wuttafarm/db/alembic/versions/3e2ef02bf264_add_activity_logs.py
deleted file mode 100644
index 5fca4be..0000000
--- a/src/wuttafarm/db/alembic/versions/3e2ef02bf264_add_activity_logs.py
+++ /dev/null
@@ -1,118 +0,0 @@
-"""add Activity Logs
-
-Revision ID: 3e2ef02bf264
-Revises: 92b813360b99
-Create Date: 2026-02-13 14:36:47.191922
-
-"""
-
-from typing import Sequence, Union
-
-from alembic import op
-import sqlalchemy as sa
-import wuttjamaican.db.util
-
-
-# revision identifiers, used by Alembic.
-revision: str = "3e2ef02bf264"
-down_revision: Union[str, None] = "92b813360b99"
-branch_labels: Union[str, Sequence[str], None] = None
-depends_on: Union[str, Sequence[str], None] = None
-
-
-def upgrade() -> None:
-
- # log_activity
- op.create_table(
- "log_activity",
- sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
- sa.Column("message", sa.String(length=255), nullable=False),
- sa.Column("timestamp", sa.DateTime(), nullable=False),
- sa.Column("status", sa.String(length=20), nullable=False),
- sa.Column("notes", sa.Text(), nullable=True),
- sa.Column("farmos_uuid", wuttjamaican.db.util.UUID(), nullable=True),
- sa.Column("drupal_id", sa.Integer(), nullable=True),
- sa.PrimaryKeyConstraint("uuid", name=op.f("pk_log_activity")),
- sa.UniqueConstraint("drupal_id", name=op.f("uq_log_activity_drupal_id")),
- sa.UniqueConstraint("farmos_uuid", name=op.f("uq_log_activity_farmos_uuid")),
- )
- op.create_table(
- "log_activity_version",
- sa.Column(
- "uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
- ),
- sa.Column("message", sa.String(length=255), autoincrement=False, nullable=True),
- sa.Column("timestamp", sa.DateTime(), autoincrement=False, nullable=True),
- sa.Column("status", sa.String(length=20), autoincrement=False, nullable=True),
- sa.Column("notes", sa.Text(), autoincrement=False, nullable=True),
- sa.Column(
- "farmos_uuid",
- wuttjamaican.db.util.UUID(),
- autoincrement=False,
- nullable=True,
- ),
- sa.Column("drupal_id", sa.Integer(), autoincrement=False, nullable=True),
- sa.Column(
- "transaction_id", sa.BigInteger(), autoincrement=False, nullable=False
- ),
- sa.Column("end_transaction_id", sa.BigInteger(), nullable=True),
- sa.Column("operation_type", sa.SmallInteger(), nullable=False),
- sa.PrimaryKeyConstraint(
- "uuid", "transaction_id", name=op.f("pk_log_activity_version")
- ),
- )
- op.create_index(
- op.f("ix_log_activity_version_end_transaction_id"),
- "log_activity_version",
- ["end_transaction_id"],
- unique=False,
- )
- op.create_index(
- op.f("ix_log_activity_version_operation_type"),
- "log_activity_version",
- ["operation_type"],
- unique=False,
- )
- op.create_index(
- "ix_log_activity_version_pk_transaction_id",
- "log_activity_version",
- ["uuid", sa.literal_column("transaction_id DESC")],
- unique=False,
- )
- op.create_index(
- "ix_log_activity_version_pk_validity",
- "log_activity_version",
- ["uuid", "transaction_id", "end_transaction_id"],
- unique=False,
- )
- op.create_index(
- op.f("ix_log_activity_version_transaction_id"),
- "log_activity_version",
- ["transaction_id"],
- unique=False,
- )
-
-
-def downgrade() -> None:
-
- # log_activity
- op.drop_index(
- op.f("ix_log_activity_version_transaction_id"),
- table_name="log_activity_version",
- )
- op.drop_index(
- "ix_log_activity_version_pk_validity", table_name="log_activity_version"
- )
- op.drop_index(
- "ix_log_activity_version_pk_transaction_id", table_name="log_activity_version"
- )
- op.drop_index(
- op.f("ix_log_activity_version_operation_type"),
- table_name="log_activity_version",
- )
- op.drop_index(
- op.f("ix_log_activity_version_end_transaction_id"),
- table_name="log_activity_version",
- )
- op.drop_table("log_activity_version")
- op.drop_table("log_activity")
diff --git a/src/wuttafarm/db/alembic/versions/4dbba8aeb1e5_add_structures.py b/src/wuttafarm/db/alembic/versions/4dbba8aeb1e5_add_structures.py
deleted file mode 100644
index 94e8186..0000000
--- a/src/wuttafarm/db/alembic/versions/4dbba8aeb1e5_add_structures.py
+++ /dev/null
@@ -1,132 +0,0 @@
-"""add Structures
-
-Revision ID: 4dbba8aeb1e5
-Revises: e416b96467fc
-Create Date: 2026-02-13 10:17:15.179202
-
-"""
-
-from typing import Sequence, Union
-
-from alembic import op
-import sqlalchemy as sa
-import wuttjamaican.db.util
-
-
-# revision identifiers, used by Alembic.
-revision: str = "4dbba8aeb1e5"
-down_revision: Union[str, None] = "e416b96467fc"
-branch_labels: Union[str, Sequence[str], None] = None
-depends_on: Union[str, Sequence[str], None] = None
-
-
-def upgrade() -> None:
-
- # structure
- op.create_table(
- "structure",
- sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
- sa.Column("name", sa.String(length=100), nullable=False),
- sa.Column("active", sa.Boolean(), nullable=False),
- sa.Column("structure_type_uuid", wuttjamaican.db.util.UUID(), nullable=False),
- sa.Column("is_location", sa.Boolean(), nullable=False),
- sa.Column("is_fixed", sa.Boolean(), nullable=False),
- sa.Column("notes", sa.Text(), nullable=True),
- sa.Column("image_url", sa.String(length=255), nullable=True),
- sa.Column("farmos_uuid", wuttjamaican.db.util.UUID(), nullable=True),
- sa.Column("drupal_id", sa.Integer(), nullable=True),
- sa.ForeignKeyConstraint(
- ["structure_type_uuid"],
- ["structure_type.uuid"],
- name=op.f("fk_structure_structure_type_uuid_structure_type"),
- ),
- sa.PrimaryKeyConstraint("uuid", name=op.f("pk_structure")),
- sa.UniqueConstraint("drupal_id", name=op.f("uq_structure_drupal_id")),
- sa.UniqueConstraint("farmos_uuid", name=op.f("uq_structure_farmos_uuid")),
- sa.UniqueConstraint("name", name=op.f("uq_structure_name")),
- )
- op.create_table(
- "structure_version",
- sa.Column(
- "uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
- ),
- sa.Column("name", sa.String(length=100), autoincrement=False, nullable=True),
- sa.Column("active", sa.Boolean(), autoincrement=False, nullable=True),
- sa.Column(
- "structure_type_uuid",
- wuttjamaican.db.util.UUID(),
- autoincrement=False,
- nullable=True,
- ),
- sa.Column("is_location", sa.Boolean(), autoincrement=False, nullable=True),
- sa.Column("is_fixed", sa.Boolean(), autoincrement=False, nullable=True),
- sa.Column("notes", sa.Text(), autoincrement=False, nullable=True),
- sa.Column(
- "image_url", sa.String(length=255), autoincrement=False, nullable=True
- ),
- sa.Column(
- "farmos_uuid",
- wuttjamaican.db.util.UUID(),
- autoincrement=False,
- nullable=True,
- ),
- sa.Column("drupal_id", sa.Integer(), autoincrement=False, nullable=True),
- sa.Column(
- "transaction_id", sa.BigInteger(), autoincrement=False, nullable=False
- ),
- sa.Column("end_transaction_id", sa.BigInteger(), nullable=True),
- sa.Column("operation_type", sa.SmallInteger(), nullable=False),
- sa.PrimaryKeyConstraint(
- "uuid", "transaction_id", name=op.f("pk_structure_version")
- ),
- )
- op.create_index(
- op.f("ix_structure_version_end_transaction_id"),
- "structure_version",
- ["end_transaction_id"],
- unique=False,
- )
- op.create_index(
- op.f("ix_structure_version_operation_type"),
- "structure_version",
- ["operation_type"],
- unique=False,
- )
- op.create_index(
- "ix_structure_version_pk_transaction_id",
- "structure_version",
- ["uuid", sa.literal_column("transaction_id DESC")],
- unique=False,
- )
- op.create_index(
- "ix_structure_version_pk_validity",
- "structure_version",
- ["uuid", "transaction_id", "end_transaction_id"],
- unique=False,
- )
- op.create_index(
- op.f("ix_structure_version_transaction_id"),
- "structure_version",
- ["transaction_id"],
- unique=False,
- )
-
-
-def downgrade() -> None:
-
- # structure
- op.drop_index(
- op.f("ix_structure_version_transaction_id"), table_name="structure_version"
- )
- op.drop_index("ix_structure_version_pk_validity", table_name="structure_version")
- op.drop_index(
- "ix_structure_version_pk_transaction_id", table_name="structure_version"
- )
- op.drop_index(
- op.f("ix_structure_version_operation_type"), table_name="structure_version"
- )
- op.drop_index(
- op.f("ix_structure_version_end_transaction_id"), table_name="structure_version"
- )
- op.drop_table("structure_version")
- op.drop_table("structure")
diff --git a/src/wuttafarm/db/alembic/versions/6c56bcd1c028_add_wuttafarmuser.py b/src/wuttafarm/db/alembic/versions/6c56bcd1c028_add_wuttafarmuser.py
deleted file mode 100644
index 0dc2d29..0000000
--- a/src/wuttafarm/db/alembic/versions/6c56bcd1c028_add_wuttafarmuser.py
+++ /dev/null
@@ -1,112 +0,0 @@
-"""add WuttaFarmUser
-
-Revision ID: 6c56bcd1c028
-Revises: 2b6385d0fa17
-Create Date: 2026-02-09 20:46:20.995903
-
-"""
-
-from typing import Sequence, Union
-
-from alembic import op
-import sqlalchemy as sa
-import wuttjamaican.db.util
-
-
-# revision identifiers, used by Alembic.
-revision: str = "6c56bcd1c028"
-down_revision: Union[str, None] = "2b6385d0fa17"
-branch_labels: Union[str, Sequence[str], None] = None
-depends_on: Union[str, Sequence[str], None] = None
-
-
-def upgrade() -> None:
-
- # wuttafarm_user
- op.create_table(
- "wuttafarm_user",
- sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
- sa.Column("farmos_uuid", wuttjamaican.db.util.UUID(), nullable=True),
- sa.Column("drupal_id", sa.Integer(), nullable=True),
- sa.ForeignKeyConstraint(
- ["uuid"], ["user.uuid"], name=op.f("fk_wuttafarm_user_uuid_user")
- ),
- sa.PrimaryKeyConstraint("uuid", name=op.f("pk_wuttafarm_user")),
- )
- op.create_table(
- "wuttafarm_user_version",
- sa.Column(
- "uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
- ),
- sa.Column(
- "farmos_uuid",
- wuttjamaican.db.util.UUID(),
- autoincrement=False,
- nullable=True,
- ),
- sa.Column("drupal_id", sa.Integer(), autoincrement=False, nullable=True),
- sa.Column(
- "transaction_id", sa.BigInteger(), autoincrement=False, nullable=False
- ),
- sa.Column("end_transaction_id", sa.BigInteger(), nullable=True),
- sa.Column("operation_type", sa.SmallInteger(), nullable=False),
- sa.PrimaryKeyConstraint(
- "uuid", "transaction_id", name=op.f("pk_wuttafarm_user_version")
- ),
- )
- op.create_index(
- op.f("ix_wuttafarm_user_version_end_transaction_id"),
- "wuttafarm_user_version",
- ["end_transaction_id"],
- unique=False,
- )
- op.create_index(
- op.f("ix_wuttafarm_user_version_operation_type"),
- "wuttafarm_user_version",
- ["operation_type"],
- unique=False,
- )
- op.create_index(
- "ix_wuttafarm_user_version_pk_transaction_id",
- "wuttafarm_user_version",
- ["uuid", sa.literal_column("transaction_id DESC")],
- unique=False,
- )
- op.create_index(
- "ix_wuttafarm_user_version_pk_validity",
- "wuttafarm_user_version",
- ["uuid", "transaction_id", "end_transaction_id"],
- unique=False,
- )
- op.create_index(
- op.f("ix_wuttafarm_user_version_transaction_id"),
- "wuttafarm_user_version",
- ["transaction_id"],
- unique=False,
- )
-
-
-def downgrade() -> None:
-
- # wuttafarm_user
- op.drop_index(
- op.f("ix_wuttafarm_user_version_transaction_id"),
- table_name="wuttafarm_user_version",
- )
- op.drop_index(
- "ix_wuttafarm_user_version_pk_validity", table_name="wuttafarm_user_version"
- )
- op.drop_index(
- "ix_wuttafarm_user_version_pk_transaction_id",
- table_name="wuttafarm_user_version",
- )
- op.drop_index(
- op.f("ix_wuttafarm_user_version_operation_type"),
- table_name="wuttafarm_user_version",
- )
- op.drop_index(
- op.f("ix_wuttafarm_user_version_end_transaction_id"),
- table_name="wuttafarm_user_version",
- )
- op.drop_table("wuttafarm_user_version")
- op.drop_table("wuttafarm_user")
diff --git a/src/wuttafarm/db/alembic/versions/92b813360b99_add_groups.py b/src/wuttafarm/db/alembic/versions/92b813360b99_add_groups.py
deleted file mode 100644
index 7223844..0000000
--- a/src/wuttafarm/db/alembic/versions/92b813360b99_add_groups.py
+++ /dev/null
@@ -1,110 +0,0 @@
-"""add Groups
-
-Revision ID: 92b813360b99
-Revises: 1b2d3224e5dc
-Create Date: 2026-02-13 13:09:48.718064
-
-"""
-
-from typing import Sequence, Union
-
-from alembic import op
-import sqlalchemy as sa
-import wuttjamaican.db.util
-
-
-# revision identifiers, used by Alembic.
-revision: str = "92b813360b99"
-down_revision: Union[str, None] = "1b2d3224e5dc"
-branch_labels: Union[str, Sequence[str], None] = None
-depends_on: Union[str, Sequence[str], None] = None
-
-
-def upgrade() -> None:
-
- # group
- op.create_table(
- "group",
- sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
- sa.Column("name", sa.String(length=100), nullable=False),
- sa.Column("is_location", sa.Boolean(), nullable=False),
- sa.Column("is_fixed", sa.Boolean(), nullable=False),
- sa.Column("active", sa.Boolean(), nullable=False),
- sa.Column("notes", sa.Text(), nullable=True),
- sa.Column("farmos_uuid", wuttjamaican.db.util.UUID(), nullable=True),
- sa.Column("drupal_id", sa.Integer(), nullable=True),
- sa.PrimaryKeyConstraint("uuid", name=op.f("pk_group")),
- sa.UniqueConstraint("drupal_id", name=op.f("uq_group_drupal_id")),
- sa.UniqueConstraint("farmos_uuid", name=op.f("uq_group_farmos_uuid")),
- sa.UniqueConstraint("name", name=op.f("uq_group_name")),
- )
- op.create_table(
- "group_version",
- sa.Column(
- "uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
- ),
- sa.Column("name", sa.String(length=100), autoincrement=False, nullable=True),
- sa.Column("is_location", sa.Boolean(), autoincrement=False, nullable=True),
- sa.Column("is_fixed", sa.Boolean(), autoincrement=False, nullable=True),
- sa.Column("active", sa.Boolean(), autoincrement=False, nullable=True),
- sa.Column("notes", sa.Text(), autoincrement=False, nullable=True),
- sa.Column(
- "farmos_uuid",
- wuttjamaican.db.util.UUID(),
- autoincrement=False,
- nullable=True,
- ),
- sa.Column("drupal_id", sa.Integer(), autoincrement=False, nullable=True),
- sa.Column(
- "transaction_id", sa.BigInteger(), autoincrement=False, nullable=False
- ),
- sa.Column("end_transaction_id", sa.BigInteger(), nullable=True),
- sa.Column("operation_type", sa.SmallInteger(), nullable=False),
- sa.PrimaryKeyConstraint(
- "uuid", "transaction_id", name=op.f("pk_group_version")
- ),
- )
- op.create_index(
- op.f("ix_group_version_end_transaction_id"),
- "group_version",
- ["end_transaction_id"],
- unique=False,
- )
- op.create_index(
- op.f("ix_group_version_operation_type"),
- "group_version",
- ["operation_type"],
- unique=False,
- )
- op.create_index(
- "ix_group_version_pk_transaction_id",
- "group_version",
- ["uuid", sa.literal_column("transaction_id DESC")],
- unique=False,
- )
- op.create_index(
- "ix_group_version_pk_validity",
- "group_version",
- ["uuid", "transaction_id", "end_transaction_id"],
- unique=False,
- )
- op.create_index(
- op.f("ix_group_version_transaction_id"),
- "group_version",
- ["transaction_id"],
- unique=False,
- )
-
-
-def downgrade() -> None:
-
- # group
- op.drop_index(op.f("ix_group_version_transaction_id"), table_name="group_version")
- op.drop_index("ix_group_version_pk_validity", table_name="group_version")
- op.drop_index("ix_group_version_pk_transaction_id", table_name="group_version")
- op.drop_index(op.f("ix_group_version_operation_type"), table_name="group_version")
- op.drop_index(
- op.f("ix_group_version_end_transaction_id"), table_name="group_version"
- )
- op.drop_table("group_version")
- op.drop_table("group")
diff --git a/src/wuttafarm/db/alembic/versions/9f2243df9566_add_land_types.py b/src/wuttafarm/db/alembic/versions/9f2243df9566_add_land_types.py
deleted file mode 100644
index 15d89fa..0000000
--- a/src/wuttafarm/db/alembic/versions/9f2243df9566_add_land_types.py
+++ /dev/null
@@ -1,110 +0,0 @@
-"""add Land Types
-
-Revision ID: 9f2243df9566
-Revises: cf3f8f46d8bc
-Create Date: 2026-02-10 19:10:02.851756
-
-"""
-
-from typing import Sequence, Union
-
-from alembic import op
-import sqlalchemy as sa
-import wuttjamaican.db.util
-
-
-# revision identifiers, used by Alembic.
-revision: str = "9f2243df9566"
-down_revision: Union[str, None] = "cf3f8f46d8bc"
-branch_labels: Union[str, Sequence[str], None] = None
-depends_on: Union[str, Sequence[str], None] = None
-
-
-def upgrade() -> None:
-
- # land_type
- op.create_table(
- "land_type",
- sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
- sa.Column("name", sa.String(length=100), nullable=False),
- sa.Column("farmos_uuid", wuttjamaican.db.util.UUID(), nullable=True),
- sa.Column("drupal_id", sa.String(length=50), nullable=True),
- sa.PrimaryKeyConstraint("uuid", name=op.f("pk_land_type")),
- sa.UniqueConstraint("drupal_id", name=op.f("uq_land_type_drupal_id")),
- sa.UniqueConstraint("farmos_uuid", name=op.f("uq_land_type_farmos_uuid")),
- sa.UniqueConstraint("name", name=op.f("uq_land_type_name")),
- )
- op.create_table(
- "land_type_version",
- sa.Column(
- "uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
- ),
- sa.Column("name", sa.String(length=100), autoincrement=False, nullable=True),
- sa.Column(
- "farmos_uuid",
- wuttjamaican.db.util.UUID(),
- autoincrement=False,
- nullable=True,
- ),
- sa.Column(
- "drupal_id", sa.String(length=50), autoincrement=False, nullable=True
- ),
- sa.Column(
- "transaction_id", sa.BigInteger(), autoincrement=False, nullable=False
- ),
- sa.Column("end_transaction_id", sa.BigInteger(), nullable=True),
- sa.Column("operation_type", sa.SmallInteger(), nullable=False),
- sa.PrimaryKeyConstraint(
- "uuid", "transaction_id", name=op.f("pk_land_type_version")
- ),
- )
- op.create_index(
- op.f("ix_land_type_version_end_transaction_id"),
- "land_type_version",
- ["end_transaction_id"],
- unique=False,
- )
- op.create_index(
- op.f("ix_land_type_version_operation_type"),
- "land_type_version",
- ["operation_type"],
- unique=False,
- )
- op.create_index(
- "ix_land_type_version_pk_transaction_id",
- "land_type_version",
- ["uuid", sa.literal_column("transaction_id DESC")],
- unique=False,
- )
- op.create_index(
- "ix_land_type_version_pk_validity",
- "land_type_version",
- ["uuid", "transaction_id", "end_transaction_id"],
- unique=False,
- )
- op.create_index(
- op.f("ix_land_type_version_transaction_id"),
- "land_type_version",
- ["transaction_id"],
- unique=False,
- )
-
-
-def downgrade() -> None:
-
- # land_type
- op.drop_index(
- op.f("ix_land_type_version_transaction_id"), table_name="land_type_version"
- )
- op.drop_index("ix_land_type_version_pk_validity", table_name="land_type_version")
- op.drop_index(
- "ix_land_type_version_pk_transaction_id", table_name="land_type_version"
- )
- op.drop_index(
- op.f("ix_land_type_version_operation_type"), table_name="land_type_version"
- )
- op.drop_index(
- op.f("ix_land_type_version_end_transaction_id"), table_name="land_type_version"
- )
- op.drop_table("land_type_version")
- op.drop_table("land_type")
diff --git a/src/wuttafarm/db/alembic/versions/cf3f8f46d8bc_add_asset_types.py b/src/wuttafarm/db/alembic/versions/cf3f8f46d8bc_add_asset_types.py
deleted file mode 100644
index ed4c344..0000000
--- a/src/wuttafarm/db/alembic/versions/cf3f8f46d8bc_add_asset_types.py
+++ /dev/null
@@ -1,115 +0,0 @@
-"""add Asset Types
-
-Revision ID: cf3f8f46d8bc
-Revises: 6c56bcd1c028
-Create Date: 2026-02-10 18:42:24.560312
-
-"""
-
-from typing import Sequence, Union
-
-from alembic import op
-import sqlalchemy as sa
-import wuttjamaican.db.util
-
-
-# revision identifiers, used by Alembic.
-revision: str = "cf3f8f46d8bc"
-down_revision: Union[str, None] = "6c56bcd1c028"
-branch_labels: Union[str, Sequence[str], None] = None
-depends_on: Union[str, Sequence[str], None] = None
-
-
-def upgrade() -> None:
-
- # asset_type
- op.create_table(
- "asset_type",
- sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
- sa.Column("name", sa.String(length=100), nullable=False),
- sa.Column("description", sa.String(length=255), nullable=True),
- sa.Column("farmos_uuid", wuttjamaican.db.util.UUID(), nullable=True),
- sa.Column("drupal_id", sa.String(length=50), nullable=True),
- sa.PrimaryKeyConstraint("uuid", name=op.f("pk_asset_type")),
- sa.UniqueConstraint("drupal_id", name=op.f("uq_asset_type_drupal_id")),
- sa.UniqueConstraint("farmos_uuid", name=op.f("uq_asset_type_farmos_uuid")),
- sa.UniqueConstraint("name", name=op.f("uq_asset_type_name")),
- )
- op.create_table(
- "asset_type_version",
- sa.Column(
- "uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
- ),
- sa.Column("name", sa.String(length=100), autoincrement=False, nullable=True),
- sa.Column(
- "description", sa.String(length=255), autoincrement=False, nullable=True
- ),
- sa.Column(
- "farmos_uuid",
- wuttjamaican.db.util.UUID(),
- autoincrement=False,
- nullable=True,
- ),
- sa.Column(
- "drupal_id", sa.String(length=50), autoincrement=False, nullable=True
- ),
- sa.Column(
- "transaction_id", sa.BigInteger(), autoincrement=False, nullable=False
- ),
- sa.Column("end_transaction_id", sa.BigInteger(), nullable=True),
- sa.Column("operation_type", sa.SmallInteger(), nullable=False),
- sa.PrimaryKeyConstraint(
- "uuid", "transaction_id", name=op.f("pk_asset_type_version")
- ),
- )
- op.create_index(
- op.f("ix_asset_type_version_end_transaction_id"),
- "asset_type_version",
- ["end_transaction_id"],
- unique=False,
- )
- op.create_index(
- op.f("ix_asset_type_version_operation_type"),
- "asset_type_version",
- ["operation_type"],
- unique=False,
- )
- op.create_index(
- "ix_asset_type_version_pk_transaction_id",
- "asset_type_version",
- ["uuid", sa.literal_column("transaction_id DESC")],
- unique=False,
- )
- op.create_index(
- "ix_asset_type_version_pk_validity",
- "asset_type_version",
- ["uuid", "transaction_id", "end_transaction_id"],
- unique=False,
- )
- op.create_index(
- op.f("ix_asset_type_version_transaction_id"),
- "asset_type_version",
- ["transaction_id"],
- unique=False,
- )
-
-
-def downgrade() -> None:
-
- # asset_type
- op.drop_index(
- op.f("ix_asset_type_version_transaction_id"), table_name="asset_type_version"
- )
- op.drop_index("ix_asset_type_version_pk_validity", table_name="asset_type_version")
- op.drop_index(
- "ix_asset_type_version_pk_transaction_id", table_name="asset_type_version"
- )
- op.drop_index(
- op.f("ix_asset_type_version_operation_type"), table_name="asset_type_version"
- )
- op.drop_index(
- op.f("ix_asset_type_version_end_transaction_id"),
- table_name="asset_type_version",
- )
- op.drop_table("asset_type_version")
- op.drop_table("asset_type")
diff --git a/src/wuttafarm/db/alembic/versions/d7479d7161a8_add_structure_types.py b/src/wuttafarm/db/alembic/versions/d7479d7161a8_add_structure_types.py
deleted file mode 100644
index b71c4a6..0000000
--- a/src/wuttafarm/db/alembic/versions/d7479d7161a8_add_structure_types.py
+++ /dev/null
@@ -1,116 +0,0 @@
-"""add Structure Types
-
-Revision ID: d7479d7161a8
-Revises: 9f2243df9566
-Create Date: 2026-02-10 19:24:20.249826
-
-"""
-
-from typing import Sequence, Union
-
-from alembic import op
-import sqlalchemy as sa
-import wuttjamaican.db.util
-
-
-# revision identifiers, used by Alembic.
-revision: str = "d7479d7161a8"
-down_revision: Union[str, None] = "9f2243df9566"
-branch_labels: Union[str, Sequence[str], None] = None
-depends_on: Union[str, Sequence[str], None] = None
-
-
-def upgrade() -> None:
-
- # structure_type
- op.create_table(
- "structure_type",
- sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
- sa.Column("name", sa.String(length=100), nullable=False),
- sa.Column("farmos_uuid", wuttjamaican.db.util.UUID(), nullable=True),
- sa.Column("drupal_id", sa.String(length=50), nullable=True),
- sa.PrimaryKeyConstraint("uuid", name=op.f("pk_structure_type")),
- sa.UniqueConstraint("drupal_id", name=op.f("uq_structure_type_drupal_id")),
- sa.UniqueConstraint("farmos_uuid", name=op.f("uq_structure_type_farmos_uuid")),
- sa.UniqueConstraint("name", name=op.f("uq_structure_type_name")),
- )
- op.create_table(
- "structure_type_version",
- sa.Column(
- "uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
- ),
- sa.Column("name", sa.String(length=100), autoincrement=False, nullable=True),
- sa.Column(
- "farmos_uuid",
- wuttjamaican.db.util.UUID(),
- autoincrement=False,
- nullable=True,
- ),
- sa.Column(
- "drupal_id", sa.String(length=50), autoincrement=False, nullable=True
- ),
- sa.Column(
- "transaction_id", sa.BigInteger(), autoincrement=False, nullable=False
- ),
- sa.Column("end_transaction_id", sa.BigInteger(), nullable=True),
- sa.Column("operation_type", sa.SmallInteger(), nullable=False),
- sa.PrimaryKeyConstraint(
- "uuid", "transaction_id", name=op.f("pk_structure_type_version")
- ),
- )
- op.create_index(
- op.f("ix_structure_type_version_end_transaction_id"),
- "structure_type_version",
- ["end_transaction_id"],
- unique=False,
- )
- op.create_index(
- op.f("ix_structure_type_version_operation_type"),
- "structure_type_version",
- ["operation_type"],
- unique=False,
- )
- op.create_index(
- "ix_structure_type_version_pk_transaction_id",
- "structure_type_version",
- ["uuid", sa.literal_column("transaction_id DESC")],
- unique=False,
- )
- op.create_index(
- "ix_structure_type_version_pk_validity",
- "structure_type_version",
- ["uuid", "transaction_id", "end_transaction_id"],
- unique=False,
- )
- op.create_index(
- op.f("ix_structure_type_version_transaction_id"),
- "structure_type_version",
- ["transaction_id"],
- unique=False,
- )
-
-
-def downgrade() -> None:
-
- # structure_type
- op.drop_index(
- op.f("ix_structure_type_version_transaction_id"),
- table_name="structure_type_version",
- )
- op.drop_index(
- "ix_structure_type_version_pk_validity", table_name="structure_type_version"
- )
- op.drop_index(
- "ix_structure_type_version_pk_transaction_id",
- table_name="structure_type_version",
- )
- op.drop_index(
- op.f("ix_structure_type_version_operation_type"),
- table_name="structure_type_version",
- )
- op.drop_index(
- op.f("ix_structure_type_version_end_transaction_id"),
- table_name="structure_type_version",
- )
- op.drop_table("structure_type_version")
- op.drop_table("structure_type")
diff --git a/src/wuttafarm/db/alembic/versions/e0d9f72575d6_add_log_types.py b/src/wuttafarm/db/alembic/versions/e0d9f72575d6_add_log_types.py
deleted file mode 100644
index 862d3be..0000000
--- a/src/wuttafarm/db/alembic/versions/e0d9f72575d6_add_log_types.py
+++ /dev/null
@@ -1,114 +0,0 @@
-"""add Log Types
-
-Revision ID: e0d9f72575d6
-Revises: d7479d7161a8
-Create Date: 2026-02-10 19:35:06.631814
-
-"""
-
-from typing import Sequence, Union
-
-from alembic import op
-import sqlalchemy as sa
-import wuttjamaican.db.util
-
-
-# revision identifiers, used by Alembic.
-revision: str = "e0d9f72575d6"
-down_revision: Union[str, None] = "d7479d7161a8"
-branch_labels: Union[str, Sequence[str], None] = None
-depends_on: Union[str, Sequence[str], None] = None
-
-
-def upgrade() -> None:
-
- # log_type
- op.create_table(
- "log_type",
- sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
- sa.Column("name", sa.String(length=100), nullable=False),
- sa.Column("description", sa.String(length=255), nullable=True),
- sa.Column("farmos_uuid", wuttjamaican.db.util.UUID(), nullable=True),
- sa.Column("drupal_id", sa.String(length=50), nullable=True),
- sa.PrimaryKeyConstraint("uuid", name=op.f("pk_log_type")),
- sa.UniqueConstraint("drupal_id", name=op.f("uq_log_type_drupal_id")),
- sa.UniqueConstraint("farmos_uuid", name=op.f("uq_log_type_farmos_uuid")),
- sa.UniqueConstraint("name", name=op.f("uq_log_type_name")),
- )
- op.create_table(
- "log_type_version",
- sa.Column(
- "uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
- ),
- sa.Column("name", sa.String(length=100), autoincrement=False, nullable=True),
- sa.Column(
- "description", sa.String(length=255), autoincrement=False, nullable=True
- ),
- sa.Column(
- "farmos_uuid",
- wuttjamaican.db.util.UUID(),
- autoincrement=False,
- nullable=True,
- ),
- sa.Column(
- "drupal_id", sa.String(length=50), autoincrement=False, nullable=True
- ),
- sa.Column(
- "transaction_id", sa.BigInteger(), autoincrement=False, nullable=False
- ),
- sa.Column("end_transaction_id", sa.BigInteger(), nullable=True),
- sa.Column("operation_type", sa.SmallInteger(), nullable=False),
- sa.PrimaryKeyConstraint(
- "uuid", "transaction_id", name=op.f("pk_log_type_version")
- ),
- )
- op.create_index(
- op.f("ix_log_type_version_end_transaction_id"),
- "log_type_version",
- ["end_transaction_id"],
- unique=False,
- )
- op.create_index(
- op.f("ix_log_type_version_operation_type"),
- "log_type_version",
- ["operation_type"],
- unique=False,
- )
- op.create_index(
- "ix_log_type_version_pk_transaction_id",
- "log_type_version",
- ["uuid", sa.literal_column("transaction_id DESC")],
- unique=False,
- )
- op.create_index(
- "ix_log_type_version_pk_validity",
- "log_type_version",
- ["uuid", "transaction_id", "end_transaction_id"],
- unique=False,
- )
- op.create_index(
- op.f("ix_log_type_version_transaction_id"),
- "log_type_version",
- ["transaction_id"],
- unique=False,
- )
-
-
-def downgrade() -> None:
-
- # log_type
- op.drop_index(
- op.f("ix_log_type_version_transaction_id"), table_name="log_type_version"
- )
- op.drop_index("ix_log_type_version_pk_validity", table_name="log_type_version")
- op.drop_index(
- "ix_log_type_version_pk_transaction_id", table_name="log_type_version"
- )
- op.drop_index(
- op.f("ix_log_type_version_operation_type"), table_name="log_type_version"
- )
- op.drop_index(
- op.f("ix_log_type_version_end_transaction_id"), table_name="log_type_version"
- )
- op.drop_table("log_type_version")
- op.drop_table("log_type")
diff --git a/src/wuttafarm/db/alembic/versions/e416b96467fc_add_land_assets.py b/src/wuttafarm/db/alembic/versions/e416b96467fc_add_land_assets.py
deleted file mode 100644
index 5f7dd87..0000000
--- a/src/wuttafarm/db/alembic/versions/e416b96467fc_add_land_assets.py
+++ /dev/null
@@ -1,132 +0,0 @@
-"""add Land Assets
-
-Revision ID: e416b96467fc
-Revises: e0d9f72575d6
-Create Date: 2026-02-13 09:39:31.327442
-
-"""
-
-from typing import Sequence, Union
-
-from alembic import op
-import sqlalchemy as sa
-import wuttjamaican.db.util
-
-
-# revision identifiers, used by Alembic.
-revision: str = "e416b96467fc"
-down_revision: Union[str, None] = "e0d9f72575d6"
-branch_labels: Union[str, Sequence[str], None] = None
-depends_on: Union[str, Sequence[str], None] = None
-
-
-def upgrade() -> None:
-
- # land_asset
- op.create_table(
- "land_asset",
- sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
- sa.Column("name", sa.String(length=100), nullable=False),
- sa.Column("land_type_uuid", wuttjamaican.db.util.UUID(), nullable=False),
- sa.Column("is_location", sa.Boolean(), nullable=False),
- sa.Column("is_fixed", sa.Boolean(), nullable=False),
- sa.Column("notes", sa.Text(), nullable=True),
- sa.Column("active", sa.Boolean(), nullable=False),
- sa.Column("farmos_uuid", wuttjamaican.db.util.UUID(), nullable=True),
- sa.Column("drupal_id", sa.Integer(), nullable=True),
- sa.ForeignKeyConstraint(
- ["land_type_uuid"],
- ["land_type.uuid"],
- name=op.f("fk_land_asset_land_type_uuid_land_type"),
- ),
- sa.PrimaryKeyConstraint("uuid", name=op.f("pk_land_asset")),
- sa.UniqueConstraint("drupal_id", name=op.f("uq_land_asset_drupal_id")),
- sa.UniqueConstraint("farmos_uuid", name=op.f("uq_land_asset_farmos_uuid")),
- sa.UniqueConstraint(
- "land_type_uuid", name=op.f("uq_land_asset_land_type_uuid")
- ),
- sa.UniqueConstraint("name", name=op.f("uq_land_asset_name")),
- )
- op.create_table(
- "land_asset_version",
- sa.Column(
- "uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
- ),
- sa.Column("name", sa.String(length=100), autoincrement=False, nullable=True),
- sa.Column(
- "land_type_uuid",
- wuttjamaican.db.util.UUID(),
- autoincrement=False,
- nullable=True,
- ),
- sa.Column("is_location", sa.Boolean(), autoincrement=False, nullable=True),
- sa.Column("is_fixed", sa.Boolean(), autoincrement=False, nullable=True),
- sa.Column("notes", sa.Text(), autoincrement=False, nullable=True),
- sa.Column("active", sa.Boolean(), autoincrement=False, nullable=True),
- sa.Column(
- "farmos_uuid",
- wuttjamaican.db.util.UUID(),
- autoincrement=False,
- nullable=True,
- ),
- sa.Column("drupal_id", sa.Integer(), autoincrement=False, nullable=True),
- sa.Column(
- "transaction_id", sa.BigInteger(), autoincrement=False, nullable=False
- ),
- sa.Column("end_transaction_id", sa.BigInteger(), nullable=True),
- sa.Column("operation_type", sa.SmallInteger(), nullable=False),
- sa.PrimaryKeyConstraint(
- "uuid", "transaction_id", name=op.f("pk_land_asset_version")
- ),
- )
- op.create_index(
- op.f("ix_land_asset_version_end_transaction_id"),
- "land_asset_version",
- ["end_transaction_id"],
- unique=False,
- )
- op.create_index(
- op.f("ix_land_asset_version_operation_type"),
- "land_asset_version",
- ["operation_type"],
- unique=False,
- )
- op.create_index(
- "ix_land_asset_version_pk_transaction_id",
- "land_asset_version",
- ["uuid", sa.literal_column("transaction_id DESC")],
- unique=False,
- )
- op.create_index(
- "ix_land_asset_version_pk_validity",
- "land_asset_version",
- ["uuid", "transaction_id", "end_transaction_id"],
- unique=False,
- )
- op.create_index(
- op.f("ix_land_asset_version_transaction_id"),
- "land_asset_version",
- ["transaction_id"],
- unique=False,
- )
-
-
-def downgrade() -> None:
-
- # land_asset
- op.drop_index(
- op.f("ix_land_asset_version_transaction_id"), table_name="land_asset_version"
- )
- op.drop_index("ix_land_asset_version_pk_validity", table_name="land_asset_version")
- op.drop_index(
- "ix_land_asset_version_pk_transaction_id", table_name="land_asset_version"
- )
- op.drop_index(
- op.f("ix_land_asset_version_operation_type"), table_name="land_asset_version"
- )
- op.drop_index(
- op.f("ix_land_asset_version_end_transaction_id"),
- table_name="land_asset_version",
- )
- op.drop_table("land_asset_version")
- op.drop_table("land_asset")
diff --git a/src/wuttafarm/db/model/__init__.py b/src/wuttafarm/db/model/__init__.py
index 27d0070..b52d7c8 100644
--- a/src/wuttafarm/db/model/__init__.py
+++ b/src/wuttafarm/db/model/__init__.py
@@ -26,13 +26,4 @@ WuttaFarm data models
# bring in all of wutta
from wuttjamaican.db.model import *
-# wutta model extensions
-from .users import WuttaFarmUser
-
-# wuttafarm proper models
-from .assets import AssetType
-from .land import LandType, LandAsset
-from .structures import StructureType, Structure
-from .animals import AnimalType, Animal
-from .groups import Group
-from .logs import LogType, ActivityLog
+# TODO: import other/custom models here...
diff --git a/src/wuttafarm/db/model/animals.py b/src/wuttafarm/db/model/animals.py
deleted file mode 100644
index e23f0c5..0000000
--- a/src/wuttafarm/db/model/animals.py
+++ /dev/null
@@ -1,194 +0,0 @@
-# -*- coding: utf-8; -*-
-################################################################################
-#
-# WuttaFarm --Web app to integrate with and extend farmOS
-# Copyright © 2026 Lance Edgar
-#
-# This file is part of WuttaFarm.
-#
-# WuttaFarm is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-#
-# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# WuttaFarm. If not, see .
-#
-################################################################################
-"""
-Model definition for Animal Types
-"""
-
-import sqlalchemy as sa
-from sqlalchemy import orm
-
-from wuttjamaican.db import model
-
-
-class AnimalType(model.Base):
- """
- Represents an "animal type" (taxonomy term) from farmOS
- """
-
- __tablename__ = "animal_type"
- __versioned__ = {
- "exclude": [
- "changed",
- ],
- }
- __wutta_hint__ = {
- "model_title": "Animal Type",
- "model_title_plural": "Animal Types",
- }
-
- uuid = model.uuid_column()
-
- name = sa.Column(
- sa.String(length=100),
- nullable=False,
- unique=True,
- doc="""
- Name of the animal type.
- """,
- )
-
- description = sa.Column(
- sa.String(length=255),
- nullable=True,
- doc="""
- Optional description for the animal type.
- """,
- )
-
- changed = sa.Column(
- sa.DateTime(),
- nullable=True,
- doc="""
- When the animal type was last changed, according to farmOS.
- """,
- )
-
- farmos_uuid = sa.Column(
- model.UUID(),
- nullable=True,
- unique=True,
- doc="""
- UUID for the animal type within farmOS.
- """,
- )
-
- drupal_id = sa.Column(
- sa.Integer(),
- nullable=True,
- unique=True,
- doc="""
- Drupal internal ID for the animal type.
- """,
- )
-
- def __str__(self):
- return self.name or ""
-
-
-class Animal(model.Base):
- """
- Represents an animal from farmOS
- """
-
- __tablename__ = "animal"
- __versioned__ = {}
- __wutta_hint__ = {
- "model_title": "Animal",
- "model_title_plural": "Animals",
- }
-
- uuid = model.uuid_column()
-
- name = sa.Column(
- sa.String(length=100),
- nullable=False,
- doc="""
- Name for the animal.
- """,
- )
-
- animal_type_uuid = model.uuid_fk_column("animal_type.uuid", nullable=False)
- animal_type = orm.relationship(
- "AnimalType",
- doc="""
- Reference to the animal type.
- """,
- )
-
- birthdate = sa.Column(
- sa.DateTime(),
- nullable=True,
- doc="""
- Birth date (and time) for the animal, if known.
- """,
- )
-
- sex = sa.Column(
- sa.String(length=1),
- nullable=True,
- doc="""
- Sex of the animal.
- """,
- )
-
- is_sterile = sa.Column(
- sa.Boolean(),
- nullable=True,
- doc="""
- Whether the animal is sterile (e.g. castrated).
- """,
- )
-
- active = sa.Column(
- sa.Boolean(),
- nullable=False,
- doc="""
- Whether the animal is currently active.
- """,
- )
-
- notes = sa.Column(
- sa.Text(),
- nullable=True,
- doc="""
- Arbitrary notes for the animal.
- """,
- )
-
- image_url = sa.Column(
- sa.String(length=255),
- nullable=True,
- doc="""
- Optional image URL for the animal.
- """,
- )
-
- farmos_uuid = sa.Column(
- model.UUID(),
- nullable=True,
- unique=True,
- doc="""
- UUID for the animal within farmOS.
- """,
- )
-
- drupal_id = sa.Column(
- sa.Integer(),
- nullable=True,
- unique=True,
- doc="""
- Drupal internal ID for the animal.
- """,
- )
-
- def __str__(self):
- return self.name or ""
diff --git a/src/wuttafarm/db/model/assets.py b/src/wuttafarm/db/model/assets.py
deleted file mode 100644
index 581be62..0000000
--- a/src/wuttafarm/db/model/assets.py
+++ /dev/null
@@ -1,82 +0,0 @@
-# -*- coding: utf-8; -*-
-################################################################################
-#
-# WuttaFarm --Web app to integrate with and extend farmOS
-# Copyright © 2026 Lance Edgar
-#
-# This file is part of WuttaFarm.
-#
-# WuttaFarm is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-#
-# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# WuttaFarm. If not, see .
-#
-################################################################################
-"""
-Model definition for Asset Types
-"""
-
-import sqlalchemy as sa
-from sqlalchemy import orm
-
-from wuttjamaican.db import model
-
-
-class AssetType(model.Base):
- """
- Represents an "asset type" from farmOS
- """
-
- __tablename__ = "asset_type"
- __versioned__ = {}
- __wutta_hint__ = {
- "model_title": "Asset Type",
- "model_title_plural": "Asset Types",
- }
-
- uuid = model.uuid_column()
-
- name = sa.Column(
- sa.String(length=100),
- nullable=False,
- unique=True,
- doc="""
- Name of the asset type.
- """,
- )
-
- description = sa.Column(
- sa.String(length=255),
- nullable=True,
- doc="""
- Description for the asset type.
- """,
- )
-
- farmos_uuid = sa.Column(
- model.UUID(),
- nullable=True,
- unique=True,
- doc="""
- UUID for the asset type within farmOS.
- """,
- )
-
- drupal_id = sa.Column(
- sa.String(length=50),
- nullable=True,
- unique=True,
- doc="""
- Drupal internal ID for the asset type.
- """,
- )
-
- def __str__(self):
- return self.name or ""
diff --git a/src/wuttafarm/db/model/groups.py b/src/wuttafarm/db/model/groups.py
deleted file mode 100644
index eae034f..0000000
--- a/src/wuttafarm/db/model/groups.py
+++ /dev/null
@@ -1,106 +0,0 @@
-# -*- coding: utf-8; -*-
-################################################################################
-#
-# WuttaFarm --Web app to integrate with and extend farmOS
-# Copyright © 2026 Lance Edgar
-#
-# This file is part of WuttaFarm.
-#
-# WuttaFarm is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-#
-# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# WuttaFarm. If not, see .
-#
-################################################################################
-"""
-Model definition for Groups
-"""
-
-import sqlalchemy as sa
-from sqlalchemy import orm
-
-from wuttjamaican.db import model
-
-
-class Group(model.Base):
- """
- Represents a "group" from farmOS
- """
-
- __tablename__ = "group"
- __versioned__ = {}
- __wutta_hint__ = {
- "model_title": "Group",
- "model_title_plural": "Groups",
- }
-
- uuid = model.uuid_column()
-
- name = sa.Column(
- sa.String(length=100),
- nullable=False,
- unique=True,
- doc="""
- Name for the group.
- """,
- )
-
- is_location = sa.Column(
- sa.Boolean(),
- nullable=False,
- doc="""
- Whether the group is considered to be a location.
- """,
- )
-
- is_fixed = sa.Column(
- sa.Boolean(),
- nullable=False,
- doc="""
- Whether the group location is fixed.
- """,
- )
-
- active = sa.Column(
- sa.Boolean(),
- nullable=False,
- doc="""
- Whether the group is active.
- """,
- )
-
- notes = sa.Column(
- sa.Text(),
- nullable=True,
- doc="""
- Arbitrary notes for the group.
- """,
- )
-
- farmos_uuid = sa.Column(
- model.UUID(),
- nullable=True,
- unique=True,
- doc="""
- UUID for the group within farmOS.
- """,
- )
-
- drupal_id = sa.Column(
- sa.Integer(),
- nullable=True,
- unique=True,
- doc="""
- Drupal internal ID for the group.
- """,
- )
-
- def __str__(self):
- return self.name or ""
diff --git a/src/wuttafarm/db/model/land.py b/src/wuttafarm/db/model/land.py
deleted file mode 100644
index 53c93cf..0000000
--- a/src/wuttafarm/db/model/land.py
+++ /dev/null
@@ -1,156 +0,0 @@
-# -*- coding: utf-8; -*-
-################################################################################
-#
-# WuttaFarm --Web app to integrate with and extend farmOS
-# Copyright © 2026 Lance Edgar
-#
-# This file is part of WuttaFarm.
-#
-# WuttaFarm is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-#
-# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# WuttaFarm. If not, see .
-#
-################################################################################
-"""
-Model definition for Land Types
-"""
-
-import sqlalchemy as sa
-from sqlalchemy import orm
-
-from wuttjamaican.db import model
-
-
-class LandType(model.Base):
- """
- Represents a "land type" from farmOS
- """
-
- __tablename__ = "land_type"
- __versioned__ = {}
- __wutta_hint__ = {
- "model_title": "Land Type",
- "model_title_plural": "Land Types",
- }
-
- uuid = model.uuid_column()
-
- name = sa.Column(
- sa.String(length=100),
- nullable=False,
- unique=True,
- doc="""
- Name of the land type.
- """,
- )
-
- farmos_uuid = sa.Column(
- model.UUID(),
- nullable=True,
- unique=True,
- doc="""
- UUID for the land type within farmOS.
- """,
- )
-
- drupal_id = sa.Column(
- sa.String(length=50),
- nullable=True,
- unique=True,
- doc="""
- Drupal internal ID for the land type.
- """,
- )
-
- land_assets = orm.relationship("LandAsset", back_populates="land_type")
-
- def __str__(self):
- return self.name or ""
-
-
-class LandAsset(model.Base):
- """
- Represents a "land asset" from farmOS
- """
-
- __tablename__ = "land_asset"
- __versioned__ = {}
- __wutta_hint__ = {
- "model_title": "Land Asset",
- "model_title_plural": "Land Assets",
- }
-
- uuid = model.uuid_column()
-
- name = sa.Column(
- sa.String(length=100),
- nullable=False,
- unique=True,
- doc="""
- Name of the land asset.
- """,
- )
-
- land_type_uuid = model.uuid_fk_column("land_type.uuid", nullable=False, unique=True)
- land_type = orm.relationship(LandType, back_populates="land_assets")
-
- is_location = sa.Column(
- sa.Boolean(),
- nullable=False,
- doc="""
- Whether the land asset should be considered a location.
- """,
- )
-
- is_fixed = sa.Column(
- sa.Boolean(),
- nullable=False,
- doc="""
- Whether the land asset's location is fixed.
- """,
- )
-
- notes = sa.Column(
- sa.Text(),
- nullable=True,
- doc="""
- Notes for the land asset.
- """,
- )
-
- active = sa.Column(
- sa.Boolean(),
- nullable=False,
- doc="""
- Whether the land asset is currently active.
- """,
- )
-
- farmos_uuid = sa.Column(
- model.UUID(),
- nullable=True,
- unique=True,
- doc="""
- UUID for the land asset within farmOS.
- """,
- )
-
- drupal_id = sa.Column(
- sa.Integer(),
- nullable=True,
- unique=True,
- doc="""
- Drupal internal ID for the land asset.
- """,
- )
-
- def __str__(self):
- return self.name or ""
diff --git a/src/wuttafarm/db/model/logs.py b/src/wuttafarm/db/model/logs.py
deleted file mode 100644
index 76f7715..0000000
--- a/src/wuttafarm/db/model/logs.py
+++ /dev/null
@@ -1,150 +0,0 @@
-# -*- coding: utf-8; -*-
-################################################################################
-#
-# WuttaFarm --Web app to integrate with and extend farmOS
-# Copyright © 2026 Lance Edgar
-#
-# This file is part of WuttaFarm.
-#
-# WuttaFarm is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-#
-# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# WuttaFarm. If not, see .
-#
-################################################################################
-"""
-Model definition for Log Types
-"""
-
-import sqlalchemy as sa
-from sqlalchemy import orm
-
-from wuttjamaican.db import model
-
-
-class LogType(model.Base):
- """
- Represents a "log type" from farmOS
- """
-
- __tablename__ = "log_type"
- __versioned__ = {}
- __wutta_hint__ = {
- "model_title": "Log Type",
- "model_title_plural": "Log Types",
- }
-
- uuid = model.uuid_column()
-
- name = sa.Column(
- sa.String(length=100),
- nullable=False,
- unique=True,
- doc="""
- Name of the log type.
- """,
- )
-
- description = sa.Column(
- sa.String(length=255),
- nullable=True,
- doc="""
- Optional description for the log type.
- """,
- )
-
- farmos_uuid = sa.Column(
- model.UUID(),
- nullable=True,
- unique=True,
- doc="""
- UUID for the log type within farmOS.
- """,
- )
-
- drupal_id = sa.Column(
- sa.String(length=50),
- nullable=True,
- unique=True,
- doc="""
- Drupal internal ID for the log type.
- """,
- )
-
- def __str__(self):
- return self.name or ""
-
-
-class ActivityLog(model.Base):
- """
- Represents an activity log from farmOS
- """
-
- __tablename__ = "log_activity"
- __versioned__ = {}
- __wutta_hint__ = {
- "model_title": "Activity Log",
- "model_title_plural": "Activity Logs",
- }
-
- uuid = model.uuid_column()
-
- message = sa.Column(
- sa.String(length=255),
- nullable=False,
- doc="""
- Message text for the log.
- """,
- )
-
- timestamp = sa.Column(
- sa.DateTime(),
- nullable=False,
- doc="""
- Date and time when the log event occurred / will occur.
- """,
- )
-
- status = sa.Column(
- sa.String(length=20),
- nullable=False,
- doc="""
- Current status of the log event.
- """,
- )
-
- notes = sa.Column(
- sa.Text(),
- nullable=True,
- doc="""
- Arbitrary notes for the log event.
- """,
- )
-
- farmos_uuid = sa.Column(
- model.UUID(),
- nullable=True,
- unique=True,
- doc="""
- UUID for the log within farmOS.
- """,
- )
-
- drupal_id = sa.Column(
- sa.Integer(),
- nullable=True,
- unique=True,
- doc="""
- Drupal internal ID for the log.
- """,
- )
-
- def __str__(self):
- return self.message or ""
diff --git a/src/wuttafarm/db/model/structures.py b/src/wuttafarm/db/model/structures.py
deleted file mode 100644
index d9fccdb..0000000
--- a/src/wuttafarm/db/model/structures.py
+++ /dev/null
@@ -1,167 +0,0 @@
-# -*- coding: utf-8; -*-
-################################################################################
-#
-# WuttaFarm --Web app to integrate with and extend farmOS
-# Copyright © 2026 Lance Edgar
-#
-# This file is part of WuttaFarm.
-#
-# WuttaFarm is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-#
-# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# WuttaFarm. If not, see .
-#
-################################################################################
-"""
-Model definition for Structure Types
-"""
-
-import sqlalchemy as sa
-from sqlalchemy import orm
-
-from wuttjamaican.db import model
-
-
-class StructureType(model.Base):
- """
- Represents a "structure type" from farmOS
- """
-
- __tablename__ = "structure_type"
- __versioned__ = {}
- __wutta_hint__ = {
- "model_title": "Structure Type",
- "model_title_plural": "Structure Types",
- }
-
- uuid = model.uuid_column()
-
- name = sa.Column(
- sa.String(length=100),
- nullable=False,
- unique=True,
- doc="""
- Name of the structure type.
- """,
- )
-
- farmos_uuid = sa.Column(
- model.UUID(),
- nullable=True,
- unique=True,
- doc="""
- UUID for the structure type within farmOS.
- """,
- )
-
- drupal_id = sa.Column(
- sa.String(length=50),
- nullable=True,
- unique=True,
- doc="""
- Drupal internal ID for the structure type.
- """,
- )
-
- def __str__(self):
- return self.name or ""
-
-
-class Structure(model.Base):
- """
- Represents a structure from farmOS
- """
-
- __tablename__ = "structure"
- __versioned__ = {}
- __wutta_hint__ = {
- "model_title": "Structure",
- "model_title_plural": "Structures",
- }
-
- uuid = model.uuid_column()
-
- name = sa.Column(
- sa.String(length=100),
- nullable=False,
- unique=True,
- doc="""
- Name for the structure.
- """,
- )
-
- active = sa.Column(
- sa.Boolean(),
- nullable=False,
- doc="""
- Whether the structure is currently active.
- """,
- )
-
- structure_type_uuid = model.uuid_fk_column("structure_type.uuid", nullable=False)
- structure_type = orm.relationship(
- "StructureType",
- doc="""
- Reference to the type of structure.
- """,
- )
-
- is_location = sa.Column(
- sa.Boolean(),
- nullable=False,
- doc="""
- Whether the structure is considered a location.
- """,
- )
-
- is_fixed = sa.Column(
- sa.Boolean(),
- nullable=False,
- doc="""
- Whether the structure location is fixed.
- """,
- )
-
- notes = sa.Column(
- sa.Text(),
- nullable=True,
- doc="""
- Arbitrary notes for the structure.
- """,
- )
-
- image_url = sa.Column(
- sa.String(length=255),
- nullable=True,
- doc="""
- Optional image URL for the structure.
- """,
- )
-
- farmos_uuid = sa.Column(
- model.UUID(),
- nullable=True,
- unique=True,
- doc="""
- UUID for the structure within farmOS.
- """,
- )
-
- drupal_id = sa.Column(
- sa.Integer(),
- nullable=True,
- unique=True,
- doc="""
- Drupal internal ID for the structure.
- """,
- )
-
- def __str__(self):
- return self.name or ""
diff --git a/src/wuttafarm/db/model/users.py b/src/wuttafarm/db/model/users.py
deleted file mode 100644
index d194175..0000000
--- a/src/wuttafarm/db/model/users.py
+++ /dev/null
@@ -1,80 +0,0 @@
-# -*- coding: utf-8; -*-
-################################################################################
-#
-# WuttaFarm --Web app to integrate with and extend farmOS
-# Copyright © 2026 Lance Edgar
-#
-# This file is part of WuttaFarm.
-#
-# WuttaFarm is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-#
-# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# WuttaFarm. If not, see .
-#
-################################################################################
-"""
-Model definition for Users (extension)
-"""
-
-import sqlalchemy as sa
-from sqlalchemy import orm
-
-from wuttjamaican.db import model
-
-
-class WuttaFarmUser(model.Base):
- """
- WuttaFarm extension for the User model.
- """
-
- __tablename__ = "wuttafarm_user"
- __versioned__ = {}
-
- uuid = model.uuid_column(sa.ForeignKey("user.uuid"), default=None)
-
- user = orm.relationship(
- model.User,
- doc="""
- Reference to the User which this record extends.
- """,
- backref=orm.backref(
- "_wuttafarm",
- uselist=False,
- cascade="all, delete-orphan",
- cascade_backrefs=False,
- doc="""
- Reference to the WuttaFarm-specific extension record for
- the user.
- """,
- ),
- )
-
- farmos_uuid = sa.Column(
- model.UUID(),
- nullable=True,
- doc="""
- UUID for the user within farmOS
- """,
- )
-
- drupal_id = sa.Column(
- sa.Integer(),
- nullable=True,
- doc="""
- Drupal internal ID for the user.
- """,
- )
-
- def __str__(self):
- return str(self.user or "")
-
-
-WuttaFarmUser.make_proxy(model.User, "_wuttafarm", "farmos_uuid")
-WuttaFarmUser.make_proxy(model.User, "_wuttafarm", "drupal_id")
diff --git a/src/wuttafarm/emails.py b/src/wuttafarm/emails.py
deleted file mode 100644
index 55b1612..0000000
--- a/src/wuttafarm/emails.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# -*- coding: utf-8; -*-
-################################################################################
-#
-# WuttaFarm --Web app to integrate with and extend farmOS
-# Copyright © 2026 Lance Edgar
-#
-# This file is part of WuttaFarm.
-#
-# WuttaFarm is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-#
-# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# WuttaFarm. If not, see .
-#
-################################################################################
-"""
-Email sending config for WuttaFarm
-"""
-
-from wuttasync.emails import ImportExportWarning
-
-
-class import_to_wuttafarm_from_farmos_warning(ImportExportWarning):
- """
- Diff warning for farmOS → WuttaFarm import.
- """
diff --git a/src/wuttafarm/importing/__init__.py b/src/wuttafarm/importing/__init__.py
deleted file mode 100644
index 6711d56..0000000
--- a/src/wuttafarm/importing/__init__.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# -*- coding: utf-8; -*-
-################################################################################
-#
-# WuttaFarm --Web app to integrate with and extend farmOS
-# Copyright © 2026 Lance Edgar
-#
-# This file is part of WuttaFarm.
-#
-# WuttaFarm is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-#
-# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# WuttaFarm. If not, see .
-#
-################################################################################
-"""
-Importing data to WuttaFarm
-"""
diff --git a/src/wuttafarm/importing/farmos.py b/src/wuttafarm/importing/farmos.py
deleted file mode 100644
index 4717c78..0000000
--- a/src/wuttafarm/importing/farmos.py
+++ /dev/null
@@ -1,620 +0,0 @@
-# -*- coding: utf-8; -*-
-################################################################################
-#
-# WuttaFarm --Web app to integrate with and extend farmOS
-# Copyright © 2026 Lance Edgar
-#
-# This file is part of WuttaFarm.
-#
-# WuttaFarm is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-#
-# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# WuttaFarm. If not, see .
-#
-################################################################################
-"""
-Data import for farmOS -> WuttaFarm
-"""
-
-import datetime
-import logging
-from uuid import UUID
-
-from oauthlib.oauth2 import BackendApplicationClient
-from requests_oauthlib import OAuth2Session
-
-from wuttasync.importing import ImportHandler, ToWuttaHandler, Importer, ToWutta
-
-from wuttafarm.db import model
-
-
-log = logging.getLogger(__name__)
-
-
-class FromFarmOSHandler(ImportHandler):
- """
- Base class for import handler using farmOS API as data source.
- """
-
- source_key = "farmos"
- generic_source_title = "farmOS"
-
- def begin_source_transaction(self):
- """
- Establish the farmOS API client.
- """
- token = self.get_farmos_oauth2_token()
- self.farmos_client = self.app.get_farmos_client(token=token)
-
- def get_farmos_oauth2_token(self):
-
- client_id = self.config.get(
- "farmos.oauth2.importing.client_id", default="wuttafarm"
- )
- client_secret = self.config.require("farmos.oauth2.importing.client_secret")
- scope = self.config.get("farmos.oauth2.importing.scope", default="farm_manager")
-
- client = BackendApplicationClient(client_id=client_id)
- oauth = OAuth2Session(client=client)
-
- return oauth.fetch_token(
- token_url=self.app.get_farmos_url("/oauth/token"),
- include_client_id=True,
- client_secret=client_secret,
- scope=scope,
- )
-
- def get_importer_kwargs(self, key, **kwargs):
- kwargs = super().get_importer_kwargs(key, **kwargs)
- kwargs["farmos_client"] = self.farmos_client
- return kwargs
-
-
-class ToWuttaFarmHandler(ToWuttaHandler):
- """
- Base class for import handler targeting WuttaFarm
- """
-
- target_key = "wuttafarm"
-
-
-class FromFarmOSToWuttaFarm(FromFarmOSHandler, ToWuttaFarmHandler):
- """
- Handler for farmOS → WuttaFarm import.
- """
-
- def define_importers(self):
- """ """
- importers = super().define_importers()
- importers["User"] = UserImporter
- importers["AssetType"] = AssetTypeImporter
- importers["LandType"] = LandTypeImporter
- importers["LandAsset"] = LandAssetImporter
- importers["StructureType"] = StructureTypeImporter
- importers["Structure"] = StructureImporter
- importers["AnimalType"] = AnimalTypeImporter
- importers["Animal"] = AnimalImporter
- importers["Group"] = GroupImporter
- importers["LogType"] = LogTypeImporter
- importers["ActivityLog"] = ActivityLogImporter
- return importers
-
-
-class FromFarmOS(Importer):
- """
- Base class for importers using farmOS API as data source.
- """
-
- key = "farmos_uuid"
-
- def get_supported_fields(self):
- """
- Auto-remove the ``uuid`` field, since we use ``farmos_uuid``
- instead for the importer key.
- """
- fields = list(super().get_supported_fields())
- if "uuid" in fields:
- fields.remove("uuid")
- return fields
-
- def normalize_datetime(self, dt):
- """
- Convert a farmOS datetime value to naive UTC used by
- WuttaFarm.
-
- :param dt: Date/time string value "as-is" from the farmOS API.
-
- :returns: Equivalent naive UTC ``datetime``
- """
- dt = datetime.datetime.fromisoformat(dt)
- return self.app.make_utc(dt)
-
-
-class ActivityLogImporter(FromFarmOS, ToWutta):
- """
- farmOS API → WuttaFarm importer for Activity Logs
- """
-
- model_class = model.ActivityLog
-
- supported_fields = [
- "farmos_uuid",
- "drupal_id",
- "message",
- "timestamp",
- "notes",
- "status",
- ]
-
- def get_source_objects(self):
- """ """
- logs = self.farmos_client.log.get("activity")
- return logs["data"]
-
- def normalize_source_object(self, log):
- """ """
-
- if notes := log["attributes"]["notes"]:
- notes = notes["value"]
-
- return {
- "farmos_uuid": UUID(log["id"]),
- "drupal_id": log["attributes"]["drupal_internal__id"],
- "message": log["attributes"]["name"],
- "timestamp": self.normalize_datetime(log["attributes"]["timestamp"]),
- "notes": notes,
- "status": log["attributes"]["status"],
- }
-
-
-class AnimalImporter(FromFarmOS, ToWutta):
- """
- farmOS API → WuttaFarm importer for Animals
- """
-
- model_class = model.Animal
-
- supported_fields = [
- "farmos_uuid",
- "drupal_id",
- "name",
- "animal_type_uuid",
- "sex",
- "is_sterile",
- "birthdate",
- "notes",
- "active",
- "image_url",
- ]
-
- def setup(self):
- super().setup()
- model = self.app.model
-
- self.animal_types_by_farmos_uuid = {}
- for animal_type in self.target_session.query(model.AnimalType):
- if animal_type.farmos_uuid:
- self.animal_types_by_farmos_uuid[animal_type.farmos_uuid] = animal_type
-
- def get_source_objects(self):
- """ """
- animals = self.farmos_client.asset.get("animal")
- return animals["data"]
-
- def normalize_source_object(self, animal):
- """ """
- animal_type_uuid = None
- image_url = None
- if relationships := animal.get("relationships"):
-
- if animal_type := relationships.get("animal_type"):
- if animal_type["data"]:
- if animal_type := self.animal_types_by_farmos_uuid.get(
- UUID(animal_type["data"]["id"])
- ):
- animal_type_uuid = animal_type.uuid
-
- if image := relationships.get("image"):
- if image["data"]:
- image = self.farmos_client.resource.get_id(
- "file", "file", image["data"][0]["id"]
- )
- if image_style := image["data"]["attributes"].get(
- "image_style_uri"
- ):
- image_url = image_style["large"]
-
- if not animal_type_uuid:
- log.warning("missing/invalid animal_type for farmOS Animal: %s", animal)
- return None
-
- birthdate = animal["attributes"]["birthdate"]
- if birthdate:
- birthdate = datetime.datetime.fromisoformat(birthdate)
- birthdate = self.app.localtime(birthdate)
- birthdate = self.app.make_utc(birthdate)
-
- if notes := animal["attributes"]["notes"]:
- notes = notes["value"]
-
- return {
- "farmos_uuid": UUID(animal["id"]),
- "drupal_id": animal["attributes"]["drupal_internal__id"],
- "name": animal["attributes"]["name"],
- "animal_type_uuid": animal_type.uuid,
- "sex": animal["attributes"]["sex"],
- "is_sterile": animal["attributes"]["is_castrated"],
- "birthdate": birthdate,
- "active": animal["attributes"]["status"] == "active",
- "notes": notes,
- "image_url": image_url,
- }
-
-
-class AnimalTypeImporter(FromFarmOS, ToWutta):
- """
- farmOS API → WuttaFarm importer for Animal Types
- """
-
- model_class = model.AnimalType
-
- supported_fields = [
- "farmos_uuid",
- "drupal_id",
- "name",
- "description",
- "changed",
- ]
-
- def get_source_objects(self):
- """ """
- animal_types = self.farmos_client.resource.get("taxonomy_term", "animal_type")
- return animal_types["data"]
-
- def normalize_source_object(self, animal_type):
- """ """
- return {
- "farmos_uuid": UUID(animal_type["id"]),
- "drupal_id": animal_type["attributes"]["drupal_internal__tid"],
- "name": animal_type["attributes"]["name"],
- "description": animal_type["attributes"]["description"],
- "changed": self.normalize_datetime(animal_type["attributes"]["changed"]),
- }
-
-
-class AssetTypeImporter(FromFarmOS, ToWutta):
- """
- farmOS API → WuttaFarm importer for Asset Types
- """
-
- model_class = model.AssetType
-
- supported_fields = [
- "farmos_uuid",
- "drupal_id",
- "name",
- "description",
- ]
-
- def get_source_objects(self):
- """ """
- asset_types = self.farmos_client.resource.get("asset_type")
- return asset_types["data"]
-
- def normalize_source_object(self, asset_type):
- """ """
- return {
- "farmos_uuid": UUID(asset_type["id"]),
- "drupal_id": asset_type["attributes"]["drupal_internal__id"],
- "name": asset_type["attributes"]["label"],
- "description": asset_type["attributes"]["description"],
- }
-
-
-class GroupImporter(FromFarmOS, ToWutta):
- """
- farmOS API → WuttaFarm importer for Groups
- """
-
- model_class = model.Group
-
- supported_fields = [
- "farmos_uuid",
- "drupal_id",
- "name",
- "is_location",
- "is_fixed",
- "notes",
- "active",
- ]
-
- def get_source_objects(self):
- """ """
- groups = self.farmos_client.asset.get("group")
- return groups["data"]
-
- def normalize_source_object(self, group):
- """ """
- if notes := group["attributes"]["notes"]:
- notes = notes["value"]
-
- return {
- "farmos_uuid": UUID(group["id"]),
- "drupal_id": group["attributes"]["drupal_internal__id"],
- "name": group["attributes"]["name"],
- "is_location": group["attributes"]["is_location"],
- "is_fixed": group["attributes"]["is_fixed"],
- "active": group["attributes"]["status"] == "active",
- "notes": notes,
- }
-
-
-class LandAssetImporter(FromFarmOS, ToWutta):
- """
- farmOS API → WuttaFarm importer for Land Assets
- """
-
- model_class = model.LandAsset
-
- supported_fields = [
- "farmos_uuid",
- "drupal_id",
- "name",
- "land_type_uuid",
- "is_location",
- "is_fixed",
- "notes",
- "active",
- ]
-
- def setup(self):
- super().setup()
- model = self.app.model
-
- self.land_types_by_id = {}
- for land_type in self.target_session.query(model.LandType):
- self.land_types_by_id[land_type.drupal_id] = land_type
-
- def get_source_objects(self):
- """ """
- land_assets = self.farmos_client.asset.get("land")
- return land_assets["data"]
-
- def normalize_source_object(self, land):
- """ """
- land_type_id = land["attributes"]["land_type"]
- land_type = self.land_types_by_id.get(land_type_id)
- if not land_type:
- log.warning(
- "invalid land_type '%s' for farmOS Land Asset: %s", land_type_id, land
- )
- return None
-
- if notes := land["attributes"]["notes"]:
- notes = notes["value"]
-
- return {
- "farmos_uuid": UUID(land["id"]),
- "drupal_id": land["attributes"]["drupal_internal__id"],
- "name": land["attributes"]["name"],
- "land_type_uuid": land_type.uuid,
- "is_location": land["attributes"]["is_location"],
- "is_fixed": land["attributes"]["is_fixed"],
- "active": land["attributes"]["status"] == "active",
- "notes": notes,
- }
-
-
-class LandTypeImporter(FromFarmOS, ToWutta):
- """
- farmOS API → WuttaFarm importer for Land Types
- """
-
- model_class = model.LandType
-
- supported_fields = [
- "farmos_uuid",
- "drupal_id",
- "name",
- ]
-
- def get_source_objects(self):
- """ """
- land_types = self.farmos_client.resource.get("land_type")
- return land_types["data"]
-
- def normalize_source_object(self, land_type):
- """ """
- return {
- "farmos_uuid": UUID(land_type["id"]),
- "drupal_id": land_type["attributes"]["drupal_internal__id"],
- "name": land_type["attributes"]["label"],
- }
-
-
-class LogTypeImporter(FromFarmOS, ToWutta):
- """
- farmOS API → WuttaFarm importer for Log Types
- """
-
- model_class = model.LogType
-
- supported_fields = [
- "farmos_uuid",
- "drupal_id",
- "name",
- "description",
- ]
-
- def get_source_objects(self):
- """ """
- log_types = self.farmos_client.resource.get("log_type")
- return log_types["data"]
-
- def normalize_source_object(self, log_type):
- """ """
- return {
- "farmos_uuid": UUID(log_type["id"]),
- "drupal_id": log_type["attributes"]["drupal_internal__id"],
- "name": log_type["attributes"]["label"],
- "description": log_type["attributes"]["description"],
- }
-
-
-class StructureImporter(FromFarmOS, ToWutta):
- """
- farmOS API → WuttaFarm importer for Structures
- """
-
- model_class = model.Structure
-
- supported_fields = [
- "farmos_uuid",
- "drupal_id",
- "name",
- "structure_type_uuid",
- "is_location",
- "is_fixed",
- "notes",
- "active",
- "image_url",
- ]
-
- def setup(self):
- super().setup()
- model = self.app.model
-
- self.structure_types_by_id = {}
- for structure_type in self.target_session.query(model.StructureType):
- self.structure_types_by_id[structure_type.drupal_id] = structure_type
-
- def get_source_objects(self):
- """ """
- structures = self.farmos_client.asset.get("structure")
- return structures["data"]
-
- def normalize_source_object(self, structure):
- """ """
- structure_type_id = structure["attributes"]["structure_type"]
- structure_type = self.structure_types_by_id.get(structure_type_id)
- if not structure_type:
- log.warning(
- "invalid structure_type '%s' for farmOS Structure: %s",
- structure_type_id,
- structure,
- )
- return None
-
- if notes := structure["attributes"]["notes"]:
- notes = notes["value"]
-
- image_url = None
- if relationships := structure.get("relationships"):
- if image := relationships.get("image"):
- if image["data"]:
- image = self.farmos_client.resource.get_id(
- "file", "file", image["data"][0]["id"]
- )
- if image_style := image["data"]["attributes"].get(
- "image_style_uri"
- ):
- image_url = image_style["large"]
-
- return {
- "farmos_uuid": UUID(structure["id"]),
- "drupal_id": structure["attributes"]["drupal_internal__id"],
- "name": structure["attributes"]["name"],
- "structure_type_uuid": structure_type.uuid,
- "is_location": structure["attributes"]["is_location"],
- "is_fixed": structure["attributes"]["is_fixed"],
- "active": structure["attributes"]["status"] == "active",
- "notes": notes,
- "image_url": image_url,
- }
-
-
-class StructureTypeImporter(FromFarmOS, ToWutta):
- """
- farmOS API → WuttaFarm importer for Structure Types
- """
-
- model_class = model.StructureType
-
- supported_fields = [
- "farmos_uuid",
- "drupal_id",
- "name",
- ]
-
- def get_source_objects(self):
- """ """
- structure_types = self.farmos_client.resource.get("structure_type")
- return structure_types["data"]
-
- def normalize_source_object(self, structure_type):
- """ """
- return {
- "farmos_uuid": UUID(structure_type["id"]),
- "drupal_id": structure_type["attributes"]["drupal_internal__id"],
- "name": structure_type["attributes"]["label"],
- }
-
-
-class UserImporter(FromFarmOS, ToWutta):
- """
- farmOS API → WuttaFarm importer for Users
- """
-
- model_class = model.User
-
- supported_fields = [
- "farmos_uuid",
- "drupal_id",
- "username",
- ]
-
- def get_simple_fields(self):
- """ """
- fields = list(super().get_simple_fields())
- # nb. must explicitly declare extension fields
- fields.extend(
- [
- "farmos_uuid",
- "drupal_id",
- ]
- )
- return fields
-
- def get_source_objects(self):
- """ """
- users = self.farmos_client.resource.get("user")
- return users["data"]
-
- def normalize_source_object(self, user):
- """ """
-
- # nb. skip Anonymous user which does not have drupal id
- drupal_id = user["attributes"].get("drupal_internal__uid")
- if not drupal_id:
- return None
-
- return {
- "farmos_uuid": UUID(user["id"]),
- "drupal_id": drupal_id,
- "username": user["attributes"]["name"],
- }
-
- def can_delete_object(self, user, data=None):
- """
- Prevent delete for users which do not exist in farmOS.
- """
- if not user.farmos_uuid:
- return False
- return True
diff --git a/src/wuttafarm/web/forms/schema.py b/src/wuttafarm/web/forms/schema.py
index f646a96..a38588a 100644
--- a/src/wuttafarm/web/forms/schema.py
+++ b/src/wuttafarm/web/forms/schema.py
@@ -27,33 +27,6 @@ import json
import colander
-from wuttaweb.forms.schema import ObjectRef
-
-
-class AnimalTypeRef(ObjectRef):
- """
- Custom schema type for a
- :class:`~wuttafarm.db.model.animals.AnimalType` reference field.
-
- This is a subclass of
- :class:`~wuttaweb:wuttaweb.forms.schema.ObjectRef`.
- """
-
- @property
- def model_class(self): # pylint: disable=empty-docstring
- """ """
- model = self.app.model
- return model.AnimalType
-
- def sort_query(self, query): # pylint: disable=empty-docstring
- """ """
- return query.order_by(self.model_class.name)
-
- def get_object_url(self, obj): # pylint: disable=empty-docstring
- """ """
- animal_type = obj
- return self.request.route_url("animal_types.view", uuid=animal_type.uuid)
-
class AnimalTypeType(colander.SchemaType):
@@ -74,31 +47,6 @@ class AnimalTypeType(colander.SchemaType):
return AnimalTypeWidget(self.request, **kwargs)
-class LandTypeRef(ObjectRef):
- """
- Custom schema type for a
- :class:`~wuttafarm.db.model.land.LandType` reference field.
-
- This is a subclass of
- :class:`~wuttaweb:wuttaweb.forms.schema.ObjectRef`.
- """
-
- @property
- def model_class(self): # pylint: disable=empty-docstring
- """ """
- model = self.app.model
- return model.LandType
-
- def sort_query(self, query): # pylint: disable=empty-docstring
- """ """
- return query.order_by(self.model_class.name)
-
- def get_object_url(self, obj): # pylint: disable=empty-docstring
- """ """
- land_type = obj
- return self.request.route_url("land_types.view", uuid=land_type.uuid)
-
-
class StructureType(colander.SchemaType):
def __init__(self, request, *args, **kwargs):
@@ -118,31 +66,6 @@ class StructureType(colander.SchemaType):
return StructureWidget(self.request, **kwargs)
-class StructureTypeRef(ObjectRef):
- """
- Custom schema type for a
- :class:`~wuttafarm.db.model.structures.Structure` reference field.
-
- This is a subclass of
- :class:`~wuttaweb:wuttaweb.forms.schema.ObjectRef`.
- """
-
- @property
- def model_class(self): # pylint: disable=empty-docstring
- """ """
- model = self.app.model
- return model.StructureType
-
- def sort_query(self, query): # pylint: disable=empty-docstring
- """ """
- return query.order_by(self.model_class.name)
-
- def get_object_url(self, obj): # pylint: disable=empty-docstring
- """ """
- structure_type = obj
- return self.request.route_url("structure_types.view", uuid=structure_type.uuid)
-
-
class UsersType(colander.SchemaType):
def __init__(self, request, *args, **kwargs):
diff --git a/src/wuttafarm/web/menus.py b/src/wuttafarm/web/menus.py
index 3e5bb46..ab6f440 100644
--- a/src/wuttafarm/web/menus.py
+++ b/src/wuttafarm/web/menus.py
@@ -33,80 +33,10 @@ class WuttaFarmMenuHandler(base.MenuHandler):
def make_menus(self, request, **kwargs):
return [
- self.make_asset_menu(request),
- self.make_log_menu(request),
self.make_farmos_menu(request),
self.make_admin_menu(request, include_people=True),
]
- def make_asset_menu(self, request):
- return {
- "title": "Assets",
- "type": "menu",
- "items": [
- {
- "title": "Animals",
- "route": "animals",
- "perm": "animals.list",
- },
- {
- "title": "Groups",
- "route": "groups",
- "perm": "groups.list",
- },
- {
- "title": "Structures",
- "route": "structures",
- "perm": "structures.list",
- },
- {
- "title": "Land",
- "route": "land_assets",
- "perm": "land_assets.list",
- },
- {"type": "sep"},
- {
- "title": "Animal Types",
- "route": "animal_types",
- "perm": "animal_types.list",
- },
- {
- "title": "Structure Types",
- "route": "structure_types",
- "perm": "structure_types.list",
- },
- {
- "title": "Land Types",
- "route": "land_types",
- "perm": "land_types.list",
- },
- {
- "title": "Asset Types",
- "route": "asset_types",
- "perm": "asset_types.list",
- },
- ],
- }
-
- def make_log_menu(self, request):
- return {
- "title": "Logs",
- "type": "menu",
- "items": [
- {
- "title": "Activity Logs",
- "route": "activity_logs",
- "perm": "activity_logs.list",
- },
- {"type": "sep"},
- {
- "title": "Log Types",
- "route": "log_types",
- "perm": "log_types.list",
- },
- ],
- }
-
def make_farmos_menu(self, request):
config = request.wutta_config
app = config.get_app()
diff --git a/src/wuttafarm/web/templates/farmos/master/view.mako b/src/wuttafarm/web/templates/farmos/master/view.mako
deleted file mode 100644
index 5e7bcd0..0000000
--- a/src/wuttafarm/web/templates/farmos/master/view.mako
+++ /dev/null
@@ -1,45 +0,0 @@
-## -*- coding: utf-8; -*-
-<%inherit file="/master/view.mako" />
-
-<%def name="tool_panels()">
- ${parent.tool_panels()}
- ${self.tool_panel_tools()}
-%def>
-
-<%def name="tool_panel_tools()">
- % if raw_json:
-
-
-
- See raw JSON data
-
-
-
- <${b}-modal :width="1200"
- % if request.use_oruga:
- v-model:active="viewJsonShowDialog"
- % else:
- :active.sync="viewJsonShowDialog"
- % endif
- >
-
-
- ${rendered_json|n}
-
-
- ${b}-modal>
-
- % endif
-%def>
-
-<%def name="modify_vue_vars()">
- ${parent.modify_vue_vars()}
- % if raw_json:
-
- % endif
-%def>
diff --git a/src/wuttafarm/web/views/__init__.py b/src/wuttafarm/web/views/__init__.py
index a4d12dd..63ce536 100644
--- a/src/wuttafarm/web/views/__init__.py
+++ b/src/wuttafarm/web/views/__init__.py
@@ -25,8 +25,6 @@ WuttaFarm Views
from wuttaweb.views import essential
-from .master import WuttaFarmMasterView
-
def includeme(config):
@@ -36,21 +34,8 @@ def includeme(config):
**{
"wuttaweb.views.auth": "wuttafarm.web.views.auth",
"wuttaweb.views.common": "wuttafarm.web.views.common",
- "wuttaweb.views.users": "wuttafarm.web.views.users",
}
)
- # native table views
- config.include("wuttafarm.web.views.asset_types")
- config.include("wuttafarm.web.views.land_types")
- config.include("wuttafarm.web.views.structure_types")
- config.include("wuttafarm.web.views.animal_types")
- config.include("wuttafarm.web.views.land_assets")
- config.include("wuttafarm.web.views.structures")
- config.include("wuttafarm.web.views.animals")
- config.include("wuttafarm.web.views.groups")
- config.include("wuttafarm.web.views.log_types")
- config.include("wuttafarm.web.views.logs_activity")
-
# views for farmOS
config.include("wuttafarm.web.views.farmos")
diff --git a/src/wuttafarm/web/views/animal_types.py b/src/wuttafarm/web/views/animal_types.py
deleted file mode 100644
index 09d1e25..0000000
--- a/src/wuttafarm/web/views/animal_types.py
+++ /dev/null
@@ -1,128 +0,0 @@
-# -*- coding: utf-8; -*-
-################################################################################
-#
-# WuttaFarm --Web app to integrate with and extend farmOS
-# Copyright © 2026 Lance Edgar
-#
-# This file is part of WuttaFarm.
-#
-# WuttaFarm is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-#
-# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# WuttaFarm. If not, see .
-#
-################################################################################
-"""
-Master view for Animal Types
-"""
-
-from wuttafarm.db.model.animals import AnimalType, Animal
-from wuttafarm.web.views import WuttaFarmMasterView
-
-
-class AnimalTypeView(WuttaFarmMasterView):
- """
- Master view for Animal Types
- """
-
- model_class = AnimalType
- route_prefix = "animal_types"
- url_prefix = "/animal-types"
-
- farmos_refurl_path = "/admin/structure/taxonomy/manage/animal_type/overview"
-
- grid_columns = [
- "name",
- "description",
- "changed",
- ]
-
- sort_defaults = "name"
-
- filter_defaults = {
- "name": {"active": True, "verb": "contains"},
- }
-
- form_fields = [
- "name",
- "description",
- "changed",
- "farmos_uuid",
- "drupal_id",
- ]
-
- has_rows = True
- row_model_class = Animal
- rows_viewable = True
-
- row_grid_columns = [
- "name",
- "sex",
- "is_sterile",
- "birthdate",
- "active",
- ]
-
- rows_sort_defaults = "name"
-
- def configure_grid(self, grid):
- g = grid
- super().configure_grid(g)
-
- # name
- g.set_link("name")
-
- def get_farmos_url(self, animal_type):
- return self.app.get_farmos_url(f"/taxonomy/term/{animal_type.drupal_id}")
-
- def get_xref_buttons(self, animal_type):
- buttons = super().get_xref_buttons(animal_type)
-
- if animal_type.farmos_uuid:
- buttons.append(
- self.make_button(
- "View farmOS record",
- primary=True,
- url=self.request.route_url(
- "farmos_animal_types.view", uuid=animal_type.farmos_uuid
- ),
- icon_left="eye",
- )
- )
-
- return buttons
-
- def get_row_grid_data(self, animal_type):
- model = self.app.model
- session = self.Session()
- return session.query(model.Animal).filter(
- model.Animal.animal_type == animal_type
- )
-
- def configure_row_grid(self, grid):
- g = grid
- super().configure_row_grid(g)
-
- # name
- g.set_link("name")
-
- def get_row_action_url_view(self, animal, i):
- return self.request.route_url("animals.view", uuid=animal.uuid)
-
-
-def defaults(config, **kwargs):
- base = globals()
-
- AnimalTypeView = kwargs.get("AnimalTypeView", base["AnimalTypeView"])
- AnimalTypeView.defaults(config)
-
-
-def includeme(config):
- defaults(config)
diff --git a/src/wuttafarm/web/views/animals.py b/src/wuttafarm/web/views/animals.py
deleted file mode 100644
index e22095e..0000000
--- a/src/wuttafarm/web/views/animals.py
+++ /dev/null
@@ -1,130 +0,0 @@
-# -*- coding: utf-8; -*-
-################################################################################
-#
-# WuttaFarm --Web app to integrate with and extend farmOS
-# Copyright © 2026 Lance Edgar
-#
-# This file is part of WuttaFarm.
-#
-# WuttaFarm is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-#
-# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# WuttaFarm. If not, see .
-#
-################################################################################
-"""
-Master view for Animals
-"""
-
-from wuttafarm.db.model.animals import Animal
-from wuttafarm.web.views import WuttaFarmMasterView
-from wuttafarm.web.forms.schema import AnimalTypeRef
-from wuttafarm.web.forms.widgets import ImageWidget
-
-
-class AnimalView(WuttaFarmMasterView):
- """
- Master view for Animals
- """
-
- model_class = Animal
- route_prefix = "animals"
- url_prefix = "/animals"
-
- farmos_refurl_path = "/assets/animal"
-
- grid_columns = [
- "name",
- "animal_type",
- "sex",
- "is_sterile",
- "birthdate",
- "active",
- ]
-
- sort_defaults = "name"
-
- filter_defaults = {
- "name": {"active": True, "verb": "contains"},
- }
-
- form_fields = [
- "name",
- "animal_type",
- "birthdate",
- "sex",
- "is_sterile",
- "active",
- "notes",
- "farmos_uuid",
- "drupal_id",
- "image_url",
- "image",
- ]
-
- def configure_grid(self, grid):
- g = grid
- super().configure_grid(g)
- model = self.app.model
-
- # name
- g.set_link("name")
-
- # animal_type
- g.set_joiner("animal_type", lambda q: q.join(model.AnimalType))
- g.set_sorter("animal_type", model.AnimalType.name)
- g.set_filter("animal_type", model.AnimalType.name, label="Animal Type Name")
-
- def configure_form(self, form):
- f = form
- super().configure_form(f)
- animal = form.model_instance
-
- # animal_type
- f.set_node("animal_type", AnimalTypeRef(self.request))
-
- # notes
- f.set_widget("notes", "notes")
-
- # image
- if animal.image_url:
- f.set_widget("image", ImageWidget("animal image"))
- f.set_default("image", animal.image_url)
-
- def get_farmos_url(self, animal):
- return self.app.get_farmos_url(f"/asset/{animal.drupal_id}")
-
- def get_xref_buttons(self, animal):
- buttons = super().get_xref_buttons(animal)
-
- if animal.farmos_uuid:
- buttons.append(
- self.make_button(
- "View farmOS record",
- primary=True,
- url=self.request.route_url(
- "farmos_animals.view", uuid=animal.farmos_uuid
- ),
- icon_left="eye",
- )
- )
-
- return buttons
-
-
-def defaults(config, **kwargs):
- base = globals()
-
- AnimalView = kwargs.get("AnimalView", base["AnimalView"])
- AnimalView.defaults(config)
-
-
-def includeme(config):
- defaults(config)
diff --git a/src/wuttafarm/web/views/asset_types.py b/src/wuttafarm/web/views/asset_types.py
deleted file mode 100644
index 775fa3a..0000000
--- a/src/wuttafarm/web/views/asset_types.py
+++ /dev/null
@@ -1,90 +0,0 @@
-# -*- coding: utf-8; -*-
-################################################################################
-#
-# WuttaFarm --Web app to integrate with and extend farmOS
-# Copyright © 2026 Lance Edgar
-#
-# This file is part of WuttaFarm.
-#
-# WuttaFarm is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-#
-# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# WuttaFarm. If not, see .
-#
-################################################################################
-"""
-Master view for Asset Types
-"""
-
-from wuttafarm.db.model.assets import AssetType
-from wuttafarm.web.views import WuttaFarmMasterView
-
-
-class AssetTypeView(WuttaFarmMasterView):
- """
- Master view for Asset Types
- """
-
- model_class = AssetType
- route_prefix = "asset_types"
- url_prefix = "/asset-types"
-
- grid_columns = [
- "name",
- "description",
- ]
-
- sort_defaults = "name"
-
- filter_defaults = {
- "name": {"active": True, "verb": "contains"},
- }
-
- form_fields = [
- "name",
- "description",
- "farmos_uuid",
- "drupal_id",
- ]
-
- def configure_grid(self, grid):
- g = grid
- super().configure_grid(g)
-
- # name
- g.set_link("name")
-
- def get_xref_buttons(self, asset_type):
- buttons = super().get_xref_buttons(asset_type)
-
- if asset_type.farmos_uuid:
- buttons.append(
- self.make_button(
- "View farmOS record",
- primary=True,
- url=self.request.route_url(
- "farmos_asset_types.view", uuid=asset_type.farmos_uuid
- ),
- icon_left="eye",
- )
- )
-
- return buttons
-
-
-def defaults(config, **kwargs):
- base = globals()
-
- AssetTypeView = kwargs.get("AssetTypeView", base["AssetTypeView"])
- AssetTypeView.defaults(config)
-
-
-def includeme(config):
- defaults(config)
diff --git a/src/wuttafarm/web/views/common.py b/src/wuttafarm/web/views/common.py
index cd68b78..f46c018 100644
--- a/src/wuttafarm/web/views/common.py
+++ b/src/wuttafarm/web/views/common.py
@@ -45,24 +45,9 @@ class CommonView(base.CommonView):
farm_viewer = auth.get_role_farm_viewer(session)
farm_viewer.notes = "this is meant to mirror the corresponding role in farmOS"
- # create system user to represent farmOS
- auth.make_user(session, username="farmos", prevent_edit=True)
-
site_admin = session.query(model.Role).filter_by(name="Site Admin").first()
if site_admin:
site_admin_perms = [
- "activity_logs.list",
- "activity_logs.view",
- "activity_logs.versions",
- "animal_types.list",
- "animal_types.view",
- "animal_types.versions",
- "animals.list",
- "animals.view",
- "animals.versions",
- "asset_types.list",
- "asset_types.view",
- "asset_types.versions",
"farmos_animal_types.list",
"farmos_animal_types.view",
"farmos_animals.list",
@@ -85,24 +70,6 @@ class CommonView(base.CommonView):
"farmos_structures.view",
"farmos_users.list",
"farmos_users.view",
- "groups.list",
- "groups.view",
- "groups.versions",
- "land_assets.list",
- "land_assets.view",
- "land_assets.versions",
- "land_types.list",
- "land_types.view",
- "land_types.versions",
- "log_types.list",
- "log_types.view",
- "log_types.versions",
- "structure_types.list",
- "structure_types.view",
- "structure_types.versions",
- "structures.list",
- "structures.view",
- "structures.versions",
]
for perm in site_admin_perms:
auth.grant_permission(site_admin, perm)
diff --git a/src/wuttafarm/web/views/farmos/animal_types.py b/src/wuttafarm/web/views/farmos/animal_types.py
index 94d02d8..a974242 100644
--- a/src/wuttafarm/web/views/farmos/animal_types.py
+++ b/src/wuttafarm/web/views/farmos/animal_types.py
@@ -79,7 +79,6 @@ class AnimalTypeView(FarmOSMasterView):
animal_type = self.farmos_client.resource.get_id(
"taxonomy_term", "animal_type", self.request.matchdict["uuid"]
)
- self.raw_json = animal_type
return self.normalize_animal_type(animal_type["data"])
def get_instance_title(self, animal_type):
@@ -96,7 +95,7 @@ class AnimalTypeView(FarmOSMasterView):
return {
"uuid": animal_type["id"],
- "drupal_id": animal_type["attributes"]["drupal_internal__tid"],
+ "drupal_internal_id": animal_type["attributes"]["drupal_internal__tid"],
"name": animal_type["attributes"]["name"],
"description": description or colander.null,
"changed": changed,
@@ -113,39 +112,18 @@ class AnimalTypeView(FarmOSMasterView):
f.set_node("changed", WuttaDateTime())
def get_xref_buttons(self, animal_type):
- model = self.app.model
- session = self.Session()
-
- buttons = [
+ return [
self.make_button(
"View in farmOS",
primary=True,
url=self.app.get_farmos_url(
- f"/taxonomy/term/{animal_type['drupal_id']}"
+ f"/taxonomy/term/{animal_type['drupal_internal_id']}"
),
target="_blank",
icon_left="external-link-alt",
- )
+ ),
]
- if wf_animal_type := (
- session.query(model.AnimalType)
- .filter(model.AnimalType.farmos_uuid == animal_type["uuid"])
- .first()
- ):
- buttons.append(
- self.make_button(
- f"View {self.app.get_title()} record",
- primary=True,
- url=self.request.route_url(
- "animal_types.view", uuid=wf_animal_type.uuid
- ),
- icon_left="eye",
- )
- )
-
- return buttons
-
def defaults(config, **kwargs):
base = globals()
diff --git a/src/wuttafarm/web/views/farmos/animals.py b/src/wuttafarm/web/views/farmos/animals.py
index 760ad34..8eca5af 100644
--- a/src/wuttafarm/web/views/farmos/animals.py
+++ b/src/wuttafarm/web/views/farmos/animals.py
@@ -27,10 +27,8 @@ import datetime
import colander
-from wuttaweb.forms.schema import WuttaDateTime
-from wuttaweb.forms.widgets import WuttaDateTimeWidget
-
from wuttafarm.web.views.farmos import FarmOSMasterView
+
from wuttafarm.web.forms.schema import UsersType, AnimalTypeType, StructureType
from wuttafarm.web.forms.widgets import ImageWidget
@@ -101,7 +99,6 @@ class AnimalView(FarmOSMasterView):
animal = self.farmos_client.resource.get_id(
"asset", "animal", self.request.matchdict["uuid"]
)
- self.raw_json = animal
# instance data
data = self.normalize_animal(animal["data"])
@@ -175,7 +172,7 @@ class AnimalView(FarmOSMasterView):
return {
"uuid": animal["id"],
- "drupal_id": animal["attributes"]["drupal_internal__id"],
+ "drupal_internal_id": animal["attributes"]["drupal_internal__id"],
"name": animal["attributes"]["name"],
"birthdate": birthdate,
"sex": animal["attributes"]["sex"],
@@ -193,10 +190,6 @@ class AnimalView(FarmOSMasterView):
# animal_type
f.set_node("animal_type", AnimalTypeType(self.request))
- # birthdate
- f.set_node("birthdate", WuttaDateTime())
- f.set_widget("birthdate", WuttaDateTimeWidget(self.request))
-
# is_castrated
f.set_node("is_castrated", colander.Boolean())
@@ -215,35 +208,16 @@ class AnimalView(FarmOSMasterView):
f.set_default("image", url)
def get_xref_buttons(self, animal):
- model = self.app.model
- session = self.Session()
-
- buttons = [
+ return [
self.make_button(
"View in farmOS",
primary=True,
- url=self.app.get_farmos_url(f"/asset/{animal['drupal_id']}"),
+ url=self.app.get_farmos_url(f"/asset/{animal['drupal_internal_id']}"),
target="_blank",
icon_left="external-link-alt",
),
]
- if wf_animal := (
- session.query(model.Animal)
- .filter(model.Animal.farmos_uuid == animal["uuid"])
- .first()
- ):
- buttons.append(
- self.make_button(
- f"View {self.app.get_title()} record",
- primary=True,
- url=self.request.route_url("animals.view", uuid=wf_animal.uuid),
- icon_left="eye",
- )
- )
-
- return buttons
-
def defaults(config, **kwargs):
base = globals()
diff --git a/src/wuttafarm/web/views/farmos/asset_types.py b/src/wuttafarm/web/views/farmos/asset_types.py
index a2fac2f..75eebbe 100644
--- a/src/wuttafarm/web/views/farmos/asset_types.py
+++ b/src/wuttafarm/web/views/farmos/asset_types.py
@@ -69,7 +69,6 @@ class AssetTypeView(FarmOSMasterView):
asset_type = self.farmos_client.resource.get_id(
"asset_type", "asset_type", self.request.matchdict["uuid"]
)
- self.raw_json = asset_type
return self.normalize_asset_type(asset_type["data"])
def get_instance_title(self, asset_type):
@@ -78,7 +77,7 @@ class AssetTypeView(FarmOSMasterView):
def normalize_asset_type(self, asset_type):
return {
"uuid": asset_type["id"],
- "drupal_id": asset_type["attributes"]["drupal_internal__id"],
+ "drupal_internal_id": asset_type["attributes"]["drupal_internal__id"],
"label": asset_type["attributes"]["label"],
"description": asset_type["attributes"]["description"],
}
@@ -90,29 +89,6 @@ class AssetTypeView(FarmOSMasterView):
# description
f.set_widget("description", "notes")
- def get_xref_buttons(self, asset_type):
- model = self.app.model
- session = self.Session()
- buttons = []
-
- if wf_asset_type := (
- session.query(model.AssetType)
- .filter(model.AssetType.farmos_uuid == asset_type["uuid"])
- .first()
- ):
- buttons.append(
- self.make_button(
- f"View {self.app.get_title()} record",
- primary=True,
- url=self.request.route_url(
- "asset_types.view", uuid=wf_asset_type.uuid
- ),
- icon_left="eye",
- )
- )
-
- return buttons
-
def defaults(config, **kwargs):
base = globals()
diff --git a/src/wuttafarm/web/views/farmos/groups.py b/src/wuttafarm/web/views/farmos/groups.py
index 66224fe..4664a6b 100644
--- a/src/wuttafarm/web/views/farmos/groups.py
+++ b/src/wuttafarm/web/views/farmos/groups.py
@@ -88,10 +88,11 @@ class GroupView(FarmOSMasterView):
g.set_renderer("changed", "datetime")
def get_instance(self):
+
group = self.farmos_client.resource.get_id(
"asset", "group", self.request.matchdict["uuid"]
)
- self.raw_json = group
+
return self.normalize_group(group["data"])
def get_instance_title(self, group):
@@ -109,7 +110,7 @@ class GroupView(FarmOSMasterView):
return {
"uuid": group["id"],
- "drupal_id": group["attributes"]["drupal_internal__id"],
+ "drupal_internal_id": group["attributes"]["drupal_internal__id"],
"name": group["attributes"]["name"],
"created": created,
"changed": changed,
@@ -141,35 +142,16 @@ class GroupView(FarmOSMasterView):
f.set_widget("changed", WuttaDateTimeWidget(self.request))
def get_xref_buttons(self, group):
- model = self.app.model
- session = self.Session()
-
- buttons = [
+ return [
self.make_button(
"View in farmOS",
primary=True,
- url=self.app.get_farmos_url(f"/asset/{group['drupal_id']}"),
+ url=self.app.get_farmos_url(f"/asset/{group['drupal_internal_id']}"),
target="_blank",
icon_left="external-link-alt",
),
]
- if wf_group := (
- session.query(model.Group)
- .filter(model.Group.farmos_uuid == group["uuid"])
- .first()
- ):
- buttons.append(
- self.make_button(
- f"View {self.app.get_title()} record",
- primary=True,
- url=self.request.route_url("groups.view", uuid=wf_group.uuid),
- icon_left="eye",
- )
- )
-
- return buttons
-
def defaults(config, **kwargs):
base = globals()
diff --git a/src/wuttafarm/web/views/farmos/land_assets.py b/src/wuttafarm/web/views/farmos/land_assets.py
index 64f43cc..a496cc5 100644
--- a/src/wuttafarm/web/views/farmos/land_assets.py
+++ b/src/wuttafarm/web/views/farmos/land_assets.py
@@ -49,7 +49,6 @@ class LandAssetView(FarmOSMasterView):
grid_columns = [
"name",
- "land_type",
"is_fixed",
"is_location",
"status",
@@ -60,7 +59,6 @@ class LandAssetView(FarmOSMasterView):
form_fields = [
"name",
- "land_type",
"is_fixed",
"is_location",
"status",
@@ -97,7 +95,6 @@ class LandAssetView(FarmOSMasterView):
land_asset = self.farmos_client.resource.get_id(
"asset", "land", self.request.matchdict["uuid"]
)
- self.raw_json = land_asset
return self.normalize_land_asset(land_asset["data"])
def get_instance_title(self, land_asset):
@@ -118,9 +115,8 @@ class LandAssetView(FarmOSMasterView):
return {
"uuid": land["id"],
- "drupal_id": land["attributes"]["drupal_internal__id"],
+ "drupal_internal_id": land["attributes"]["drupal_internal__id"],
"name": land["attributes"]["name"],
- "land_type": land["attributes"]["land_type"],
"created": created,
"changed": changed,
"is_fixed": land["attributes"]["is_fixed"],
@@ -155,42 +151,12 @@ class LandAssetView(FarmOSMasterView):
self.make_button(
"View in farmOS",
primary=True,
- url=self.app.get_farmos_url(f"/asset/{land['drupal_id']}"),
+ url=self.app.get_farmos_url(f"/asset/{land['drupal_internal_id']}"),
target="_blank",
icon_left="external-link-alt",
),
]
- def get_xref_buttons(self, land):
- model = self.app.model
- session = self.Session()
-
- buttons = [
- self.make_button(
- "View in farmOS",
- primary=True,
- url=self.app.get_farmos_url(f"/asset/{land['drupal_id']}"),
- target="_blank",
- icon_left="external-link-alt",
- ),
- ]
-
- if wf_land := (
- session.query(model.LandAsset)
- .filter(model.LandAsset.farmos_uuid == land["uuid"])
- .first()
- ):
- buttons.append(
- self.make_button(
- f"View {self.app.get_title()} record",
- primary=True,
- url=self.request.route_url("land_assets.view", uuid=wf_land.uuid),
- icon_left="eye",
- )
- )
-
- return buttons
-
def defaults(config, **kwargs):
base = globals()
diff --git a/src/wuttafarm/web/views/farmos/land_types.py b/src/wuttafarm/web/views/farmos/land_types.py
index e9eccea..aadece8 100644
--- a/src/wuttafarm/web/views/farmos/land_types.py
+++ b/src/wuttafarm/web/views/farmos/land_types.py
@@ -64,7 +64,6 @@ class LandTypeView(FarmOSMasterView):
land_type = self.farmos_client.resource.get_id(
"land_type", "land_type", self.request.matchdict["uuid"]
)
- self.raw_json = land_type
return self.normalize_land_type(land_type["data"])
def get_instance_title(self, land_type):
@@ -73,33 +72,10 @@ class LandTypeView(FarmOSMasterView):
def normalize_land_type(self, land_type):
return {
"uuid": land_type["id"],
- "drupal_id": land_type["attributes"]["drupal_internal__id"],
+ "drupal_internal_id": land_type["attributes"]["drupal_internal__id"],
"label": land_type["attributes"]["label"],
}
- def get_xref_buttons(self, land_type):
- model = self.app.model
- session = self.Session()
- buttons = []
-
- if wf_land_type := (
- session.query(model.LandType)
- .filter(model.LandType.farmos_uuid == land_type["uuid"])
- .first()
- ):
- buttons.append(
- self.make_button(
- f"View {self.app.get_title()} record",
- primary=True,
- url=self.request.route_url(
- "land_types.view", uuid=wf_land_type.uuid
- ),
- icon_left="eye",
- )
- )
-
- return buttons
-
def defaults(config, **kwargs):
base = globals()
diff --git a/src/wuttafarm/web/views/farmos/log_types.py b/src/wuttafarm/web/views/farmos/log_types.py
index 1f6404a..6e72f8f 100644
--- a/src/wuttafarm/web/views/farmos/log_types.py
+++ b/src/wuttafarm/web/views/farmos/log_types.py
@@ -66,7 +66,6 @@ class LogTypeView(FarmOSMasterView):
log_type = self.farmos_client.resource.get_id(
"log_type", "log_type", self.request.matchdict["uuid"]
)
- self.raw_json = log_type
return self.normalize_log_type(log_type["data"])
def get_instance_title(self, log_type):
@@ -75,7 +74,7 @@ class LogTypeView(FarmOSMasterView):
def normalize_log_type(self, log_type):
return {
"uuid": log_type["id"],
- "drupal_id": log_type["attributes"]["drupal_internal__id"],
+ "drupal_internal_id": log_type["attributes"]["drupal_internal__id"],
"label": log_type["attributes"]["label"],
"description": log_type["attributes"]["description"],
}
@@ -87,27 +86,6 @@ class LogTypeView(FarmOSMasterView):
# description
f.set_widget("description", "notes")
- def get_xref_buttons(self, log_type):
- model = self.app.model
- session = self.Session()
- buttons = []
-
- if wf_log_type := (
- session.query(model.LogType)
- .filter(model.LogType.farmos_uuid == log_type["uuid"])
- .first()
- ):
- buttons.append(
- self.make_button(
- f"View {self.app.get_title()} record",
- primary=True,
- url=self.request.route_url("log_types.view", uuid=wf_log_type.uuid),
- icon_left="eye",
- )
- )
-
- return buttons
-
def defaults(config, **kwargs):
base = globals()
diff --git a/src/wuttafarm/web/views/farmos/logs_activity.py b/src/wuttafarm/web/views/farmos/logs_activity.py
index e966810..61b4e85 100644
--- a/src/wuttafarm/web/views/farmos/logs_activity.py
+++ b/src/wuttafarm/web/views/farmos/logs_activity.py
@@ -79,7 +79,6 @@ class ActivityLogView(FarmOSMasterView):
def get_instance(self):
log = self.farmos_client.log.get_id("activity", self.request.matchdict["uuid"])
- self.raw_json = log
return self.normalize_log(log["data"])
def get_instance_title(self, log):
@@ -96,7 +95,7 @@ class ActivityLogView(FarmOSMasterView):
return {
"uuid": log["id"],
- "drupal_id": log["attributes"]["drupal_internal__id"],
+ "drupal_internal_id": log["attributes"]["drupal_internal__id"],
"name": log["attributes"]["name"],
"timestamp": timestamp,
"status": log["attributes"]["status"],
@@ -115,35 +114,16 @@ class ActivityLogView(FarmOSMasterView):
f.set_widget("notes", "notes")
def get_xref_buttons(self, log):
- model = self.app.model
- session = self.Session()
-
- buttons = [
+ return [
self.make_button(
"View in farmOS",
primary=True,
- url=self.app.get_farmos_url(f"/log/{log['drupal_id']}"),
+ url=self.app.get_farmos_url(f"/log/{log['drupal_internal_id']}"),
target="_blank",
icon_left="external-link-alt",
),
]
- if wf_log := (
- session.query(model.ActivityLog)
- .filter(model.ActivityLog.farmos_uuid == log["uuid"])
- .first()
- ):
- buttons.append(
- self.make_button(
- f"View {self.app.get_title()} record",
- primary=True,
- url=self.request.route_url("activity_logs.view", uuid=wf_log.uuid),
- icon_left="eye",
- )
- )
-
- return buttons
-
def defaults(config, **kwargs):
base = globals()
diff --git a/src/wuttafarm/web/views/farmos/master.py b/src/wuttafarm/web/views/farmos/master.py
index 955120b..59003d0 100644
--- a/src/wuttafarm/web/views/farmos/master.py
+++ b/src/wuttafarm/web/views/farmos/master.py
@@ -23,10 +23,6 @@
Base class for farmOS master views
"""
-import json
-
-import markdown
-
from wuttaweb.views import MasterView
from wuttafarm.web.util import save_farmos_oauth2_token
@@ -58,7 +54,6 @@ class FarmOSMasterView(MasterView):
def __init__(self, request, context=None):
super().__init__(request, context=context)
self.farmos_client = self.get_farmos_client()
- self.raw_json = None
def get_farmos_client(self):
token = self.request.session.get("farmos.oauth2.token")
@@ -76,26 +71,9 @@ class FarmOSMasterView(MasterView):
return self.app.get_farmos_client(token=token, token_updater=token_updater)
- def get_fallback_templates(self, template):
- """ """
- templates = super().get_fallback_templates(template)
-
- if template == "view":
- templates.insert(0, "/farmos/master/view.mako")
-
- return templates
-
def get_template_context(self, context):
if self.listing and self.farmos_refurl_path:
context["farmos_refurl"] = self.app.get_farmos_url(self.farmos_refurl_path)
- if self.viewing and self.raw_json:
- context["raw_json"] = self.raw_json
- code = "```json\n" + json.dumps(self.raw_json, indent=2) + "\n```"
- # TODO: this does not seem to be adding syntax highlight
- context["rendered_json"] = markdown.markdown(
- code, extensions=["fenced_code", "codehilite"]
- )
-
return context
diff --git a/src/wuttafarm/web/views/farmos/structure_types.py b/src/wuttafarm/web/views/farmos/structure_types.py
index b7e58d8..3fe4741 100644
--- a/src/wuttafarm/web/views/farmos/structure_types.py
+++ b/src/wuttafarm/web/views/farmos/structure_types.py
@@ -66,7 +66,6 @@ class StructureTypeView(FarmOSMasterView):
structure_type = self.farmos_client.resource.get_id(
"structure_type", "structure_type", self.request.matchdict["uuid"]
)
- self.raw_json = structure_type
return self.normalize_structure_type(structure_type["data"])
def get_instance_title(self, structure_type):
@@ -75,33 +74,10 @@ class StructureTypeView(FarmOSMasterView):
def normalize_structure_type(self, structure_type):
return {
"uuid": structure_type["id"],
- "drupal_id": structure_type["attributes"]["drupal_internal__id"],
+ "drupal_internal_id": structure_type["attributes"]["drupal_internal__id"],
"label": structure_type["attributes"]["label"],
}
- def get_xref_buttons(self, structure_type):
- model = self.app.model
- session = self.Session()
- buttons = []
-
- if wf_structure_type := (
- session.query(model.StructureType)
- .filter(model.StructureType.farmos_uuid == structure_type["uuid"])
- .first()
- ):
- buttons.append(
- self.make_button(
- f"View {self.app.get_title()} record",
- primary=True,
- url=self.request.route_url(
- "structure_types.view", uuid=wf_structure_type.uuid
- ),
- icon_left="eye",
- )
- )
-
- return buttons
-
def defaults(config, **kwargs):
base = globals()
diff --git a/src/wuttafarm/web/views/farmos/structures.py b/src/wuttafarm/web/views/farmos/structures.py
index 3626fb1..bbc4f1f 100644
--- a/src/wuttafarm/web/views/farmos/structures.py
+++ b/src/wuttafarm/web/views/farmos/structures.py
@@ -94,7 +94,7 @@ class StructureView(FarmOSMasterView):
structure = self.farmos_client.resource.get_id(
"asset", "structure", self.request.matchdict["uuid"]
)
- self.raw_json = structure
+
data = self.normalize_structure(structure["data"])
if relationships := structure["data"].get("relationships"):
@@ -147,7 +147,7 @@ class StructureView(FarmOSMasterView):
return {
"uuid": structure["id"],
- "drupal_id": structure["attributes"]["drupal_internal__id"],
+ "drupal_internal_id": structure["attributes"]["drupal_internal__id"],
"name": structure["attributes"]["name"],
"structure_type": structure["attributes"]["structure_type"],
"is_fixed": structure["attributes"]["is_fixed"],
@@ -186,37 +186,17 @@ class StructureView(FarmOSMasterView):
f.set_default("image", url)
def get_xref_buttons(self, structure):
- model = self.app.model
- session = self.Session()
-
- buttons = [
+ drupal_id = structure["drupal_internal_id"]
+ return [
self.make_button(
"View in farmOS",
primary=True,
- url=self.app.get_farmos_url(f"/asset/{structure['drupal_id']}"),
+ url=self.app.get_farmos_url(f"/asset/{drupal_id}"),
target="_blank",
icon_left="external-link-alt",
),
]
- if wf_structure := (
- session.query(model.Structure)
- .filter(model.Structure.farmos_uuid == structure["uuid"])
- .first()
- ):
- buttons.append(
- self.make_button(
- f"View {self.app.get_title()} record",
- primary=True,
- url=self.request.route_url(
- "structures.view", uuid=wf_structure.uuid
- ),
- icon_left="eye",
- )
- )
-
- return buttons
-
def defaults(config, **kwargs):
base = globals()
diff --git a/src/wuttafarm/web/views/farmos/users.py b/src/wuttafarm/web/views/farmos/users.py
index bb004ee..317bfe3 100644
--- a/src/wuttafarm/web/views/farmos/users.py
+++ b/src/wuttafarm/web/views/farmos/users.py
@@ -77,7 +77,6 @@ class UserView(FarmOSMasterView):
user = self.farmos_client.resource.get_id(
"user", "user", self.request.matchdict["uuid"]
)
- self.raw_json = user
return self.normalize_user(user["data"])
def get_instance_title(self, user):
@@ -95,7 +94,7 @@ class UserView(FarmOSMasterView):
return {
"uuid": user["id"],
- "drupal_id": user["attributes"].get("drupal_internal__uid"),
+ "drupal_internal_id": user["attributes"].get("drupal_internal__uid"),
"display_name": user["attributes"]["display_name"],
"name": user["attributes"].get("name") or colander.null,
"mail": user["attributes"].get("mail") or colander.null,
@@ -116,36 +115,17 @@ class UserView(FarmOSMasterView):
f.set_node("changed", WuttaDateTime())
def get_xref_buttons(self, user):
- model = self.app.model
- session = self.Session()
- buttons = []
-
- if drupal_id := user["drupal_id"]:
- buttons.append(
+ if drupal_id := user["drupal_internal_id"]:
+ return [
self.make_button(
"View in farmOS",
primary=True,
url=self.app.get_farmos_url(f"/user/{drupal_id}"),
target="_blank",
icon_left="external-link-alt",
- )
- )
-
- if wf_user := (
- session.query(model.WuttaFarmUser)
- .filter(model.WuttaFarmUser.farmos_uuid == user["uuid"])
- .first()
- ):
- buttons.append(
- self.make_button(
- f"View {self.app.get_title()} record",
- primary=True,
- url=self.request.route_url("users.view", uuid=wf_user.uuid),
- icon_left="eye",
- )
- )
-
- return buttons
+ ),
+ ]
+ return None
def defaults(config, **kwargs):
diff --git a/src/wuttafarm/web/views/groups.py b/src/wuttafarm/web/views/groups.py
deleted file mode 100644
index 5f2746b..0000000
--- a/src/wuttafarm/web/views/groups.py
+++ /dev/null
@@ -1,107 +0,0 @@
-# -*- coding: utf-8; -*-
-################################################################################
-#
-# WuttaFarm --Web app to integrate with and extend farmOS
-# Copyright © 2026 Lance Edgar
-#
-# This file is part of WuttaFarm.
-#
-# WuttaFarm is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-#
-# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# WuttaFarm. If not, see .
-#
-################################################################################
-"""
-Master view for Groups
-"""
-
-from wuttafarm.db.model.groups import Group
-from wuttafarm.web.views import WuttaFarmMasterView
-
-
-class GroupView(WuttaFarmMasterView):
- """
- Master view for Groups
- """
-
- model_class = Group
- route_prefix = "groups"
- url_prefix = "/groups"
-
- farmos_refurl_path = "/assets/group"
-
- grid_columns = [
- "name",
- "is_location",
- "is_fixed",
- "active",
- ]
-
- sort_defaults = "name"
-
- filter_defaults = {
- "name": {"active": True, "verb": "contains"},
- }
-
- form_fields = [
- "name",
- "is_location",
- "is_fixed",
- "active",
- "notes",
- "farmos_uuid",
- "drupal_id",
- ]
-
- def configure_grid(self, grid):
- g = grid
- super().configure_grid(g)
-
- # name
- g.set_link("name")
-
- def configure_form(self, form):
- f = form
- super().configure_form(f)
-
- # notes
- f.set_widget("notes", "notes")
-
- def get_farmos_url(self, group):
- return self.app.get_farmos_url(f"/asset/{group.drupal_id}")
-
- def get_xref_buttons(self, group):
- buttons = super().get_xref_buttons(group)
-
- if group.farmos_uuid:
- buttons.append(
- self.make_button(
- "View farmOS record",
- primary=True,
- url=self.request.route_url(
- "farmos_groups.view", uuid=group.farmos_uuid
- ),
- icon_left="eye",
- )
- )
-
- return buttons
-
-
-def defaults(config, **kwargs):
- base = globals()
-
- GroupView = kwargs.get("GroupView", base["GroupView"])
- GroupView.defaults(config)
-
-
-def includeme(config):
- defaults(config)
diff --git a/src/wuttafarm/web/views/land_assets.py b/src/wuttafarm/web/views/land_assets.py
deleted file mode 100644
index 18f7a3d..0000000
--- a/src/wuttafarm/web/views/land_assets.py
+++ /dev/null
@@ -1,117 +0,0 @@
-# -*- coding: utf-8; -*-
-################################################################################
-#
-# WuttaFarm --Web app to integrate with and extend farmOS
-# Copyright © 2026 Lance Edgar
-#
-# This file is part of WuttaFarm.
-#
-# WuttaFarm is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-#
-# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# WuttaFarm. If not, see .
-#
-################################################################################
-"""
-Master view for Land Assets
-"""
-
-from wuttafarm.db.model.land import LandAsset
-from wuttafarm.web.views import WuttaFarmMasterView
-from wuttafarm.web.forms.schema import LandTypeRef
-
-
-class LandAssetView(WuttaFarmMasterView):
- """
- Master view for Land Assets
- """
-
- model_class = LandAsset
- route_prefix = "land_assets"
- url_prefix = "/land-assets"
-
- farmos_refurl_path = "/assets/land"
-
- grid_columns = [
- "name",
- "land_type",
- "is_location",
- "is_fixed",
- "notes",
- "active",
- ]
-
- sort_defaults = "name"
-
- filter_defaults = {
- "name": {"active": True, "verb": "contains"},
- }
-
- form_fields = [
- "name",
- "land_type",
- "is_location",
- "is_fixed",
- "notes",
- "active",
- "farmos_uuid",
- "drupal_id",
- ]
-
- def configure_grid(self, grid):
- g = grid
- super().configure_grid(g)
- model = self.app.model
-
- # name
- g.set_link("name")
-
- # land_type
- g.set_joiner("land_type", lambda q: q.join(model.LandType))
- g.set_sorter("land_type", model.LandType.name)
- g.set_filter("land_type", model.LandType.name, label="Land Type Name")
-
- def configure_form(self, form):
- f = form
- super().configure_form(f)
-
- # land_type
- f.set_node("land_type", LandTypeRef(self.request))
-
- def get_farmos_url(self, land):
- return self.app.get_farmos_url(f"/asset/{land.drupal_id}")
-
- def get_xref_buttons(self, land_asset):
- buttons = super().get_xref_buttons(land_asset)
-
- if land_asset.farmos_uuid:
- buttons.append(
- self.make_button(
- "View farmOS record",
- primary=True,
- url=self.request.route_url(
- "farmos_land_assets.view", uuid=land_asset.farmos_uuid
- ),
- icon_left="eye",
- )
- )
-
- return buttons
-
-
-def defaults(config, **kwargs):
- base = globals()
-
- LandAssetView = kwargs.get("LandAssetView", base["LandAssetView"])
- LandAssetView.defaults(config)
-
-
-def includeme(config):
- defaults(config)
diff --git a/src/wuttafarm/web/views/land_types.py b/src/wuttafarm/web/views/land_types.py
deleted file mode 100644
index 21bfabc..0000000
--- a/src/wuttafarm/web/views/land_types.py
+++ /dev/null
@@ -1,118 +0,0 @@
-# -*- coding: utf-8; -*-
-################################################################################
-#
-# WuttaFarm --Web app to integrate with and extend farmOS
-# Copyright © 2026 Lance Edgar
-#
-# This file is part of WuttaFarm.
-#
-# WuttaFarm is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-#
-# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# WuttaFarm. If not, see .
-#
-################################################################################
-"""
-Master view for Land Types
-"""
-
-from wuttafarm.db.model.land import LandType, LandAsset
-from wuttafarm.web.views import WuttaFarmMasterView
-
-
-class LandTypeView(WuttaFarmMasterView):
- """
- Master view for Land Types
- """
-
- model_class = LandType
- route_prefix = "land_types"
- url_prefix = "/land-types"
-
- grid_columns = [
- "name",
- ]
-
- sort_defaults = "name"
-
- filter_defaults = {
- "name": {"active": True, "verb": "contains"},
- }
-
- form_fields = [
- "name",
- "farmos_uuid",
- "drupal_id",
- ]
-
- has_rows = True
- row_model_class = LandAsset
- rows_viewable = True
-
- row_grid_columns = [
- "name",
- "is_location",
- "is_fixed",
- "active",
- ]
-
- rows_sort_defaults = "name"
-
- def configure_grid(self, grid):
- g = grid
- super().configure_grid(g)
-
- # name
- g.set_link("name")
-
- def get_xref_buttons(self, land_type):
- buttons = super().get_xref_buttons(land_type)
-
- if land_type.farmos_uuid:
- buttons.append(
- self.make_button(
- "View farmOS record",
- primary=True,
- url=self.request.route_url(
- "farmos_land_types.view", uuid=land_type.farmos_uuid
- ),
- icon_left="eye",
- )
- )
-
- return buttons
-
- def get_row_grid_data(self, land_type):
- model = self.app.model
- session = self.Session()
- return session.query(model.LandAsset).filter(
- model.LandAsset.land_type == land_type
- )
-
- def configure_row_grid(self, grid):
- g = grid
- super().configure_row_grid(g)
-
- # name
- g.set_link("name")
-
- def get_row_action_url_view(self, land_asset, i):
- return self.request.route_url("land_assets.view", uuid=land_asset.uuid)
-
-
-def defaults(config, **kwargs):
- base = globals()
-
- LandTypeView = kwargs.get("LandTypeView", base["LandTypeView"])
- LandTypeView.defaults(config)
-
-
-def includeme(config):
- defaults(config)
diff --git a/src/wuttafarm/web/views/log_types.py b/src/wuttafarm/web/views/log_types.py
deleted file mode 100644
index 13ea35f..0000000
--- a/src/wuttafarm/web/views/log_types.py
+++ /dev/null
@@ -1,90 +0,0 @@
-# -*- coding: utf-8; -*-
-################################################################################
-#
-# WuttaFarm --Web app to integrate with and extend farmOS
-# Copyright © 2026 Lance Edgar
-#
-# This file is part of WuttaFarm.
-#
-# WuttaFarm is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-#
-# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# WuttaFarm. If not, see .
-#
-################################################################################
-"""
-Master view for Log Types
-"""
-
-from wuttafarm.db.model.logs import LogType
-from wuttafarm.web.views import WuttaFarmMasterView
-
-
-class LogTypeView(WuttaFarmMasterView):
- """
- Master view for Log Types
- """
-
- model_class = LogType
- route_prefix = "log_types"
- url_prefix = "/log-types"
-
- grid_columns = [
- "name",
- "description",
- ]
-
- sort_defaults = "name"
-
- filter_defaults = {
- "name": {"active": True, "verb": "contains"},
- }
-
- form_fields = [
- "name",
- "description",
- "farmos_uuid",
- "drupal_id",
- ]
-
- def configure_grid(self, grid):
- g = grid
- super().configure_grid(g)
-
- # name
- g.set_link("name")
-
- def get_xref_buttons(self, log_type):
- buttons = super().get_xref_buttons(log_type)
-
- if log_type.farmos_uuid:
- buttons.append(
- self.make_button(
- "View farmOS record",
- primary=True,
- url=self.request.route_url(
- "farmos_log_types.view", uuid=log_type.farmos_uuid
- ),
- icon_left="eye",
- )
- )
-
- return buttons
-
-
-def defaults(config, **kwargs):
- base = globals()
-
- LogTypeView = kwargs.get("LogTypeView", base["LogTypeView"])
- LogTypeView.defaults(config)
-
-
-def includeme(config):
- defaults(config)
diff --git a/src/wuttafarm/web/views/logs_activity.py b/src/wuttafarm/web/views/logs_activity.py
deleted file mode 100644
index a2b2154..0000000
--- a/src/wuttafarm/web/views/logs_activity.py
+++ /dev/null
@@ -1,105 +0,0 @@
-# -*- coding: utf-8; -*-
-################################################################################
-#
-# WuttaFarm --Web app to integrate with and extend farmOS
-# Copyright © 2026 Lance Edgar
-#
-# This file is part of WuttaFarm.
-#
-# WuttaFarm is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-#
-# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# WuttaFarm. If not, see .
-#
-################################################################################
-"""
-Master view for Activity Logs
-"""
-
-from wuttafarm.db.model.logs import ActivityLog
-from wuttafarm.web.views import WuttaFarmMasterView
-
-
-class ActivityLogView(WuttaFarmMasterView):
- """
- Master view for Activity Logs
- """
-
- model_class = ActivityLog
- route_prefix = "activity_logs"
- url_prefix = "/logs/activity"
-
- farmos_refurl_path = "/logs/activity"
-
- grid_columns = [
- "message",
- "timestamp",
- "status",
- ]
-
- sort_defaults = ("timestamp", "desc")
-
- filter_defaults = {
- "message": {"active": True, "verb": "contains"},
- }
-
- form_fields = [
- "message",
- "timestamp",
- "status",
- "notes",
- "farmos_uuid",
- "drupal_id",
- ]
-
- def configure_grid(self, grid):
- g = grid
- super().configure_grid(g)
-
- # message
- g.set_link("message")
-
- def configure_form(self, form):
- f = form
- super().configure_form(f)
-
- # notes
- f.set_widget("notes", "notes")
-
- def get_farmos_url(self, log):
- return self.app.get_farmos_url(f"/log/{log.drupal_id}")
-
- def get_xref_buttons(self, log):
- buttons = super().get_xref_buttons(log)
-
- if log.farmos_uuid:
- buttons.append(
- self.make_button(
- "View farmOS record",
- primary=True,
- url=self.request.route_url(
- "farmos_logs_activity.view", uuid=log.farmos_uuid
- ),
- icon_left="eye",
- )
- )
-
- return buttons
-
-
-def defaults(config, **kwargs):
- base = globals()
-
- ActivityLogView = kwargs.get("ActivityLogView", base["ActivityLogView"])
- ActivityLogView.defaults(config)
-
-
-def includeme(config):
- defaults(config)
diff --git a/src/wuttafarm/web/views/master.py b/src/wuttafarm/web/views/master.py
deleted file mode 100644
index 7ff165b..0000000
--- a/src/wuttafarm/web/views/master.py
+++ /dev/null
@@ -1,70 +0,0 @@
-# -*- coding: utf-8; -*-
-################################################################################
-#
-# WuttaFarm --Web app to integrate with and extend farmOS
-# Copyright © 2026 Lance Edgar
-#
-# This file is part of WuttaFarm.
-#
-# WuttaFarm is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-#
-# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# WuttaFarm. If not, see .
-#
-################################################################################
-"""
-Base class for WuttaFarm master views
-"""
-
-from wuttaweb.views import MasterView
-
-
-class WuttaFarmMasterView(MasterView):
- """
- Base class for WuttaFarm master views
- """
-
- farmos_refurl_path = None
-
- labels = {
- "farmos_uuid": "farmOS UUID",
- "drupal_id": "Drupal ID",
- "image_url": "Image URL",
- }
-
- row_labels = {
- "farmos_uuid": "farmOS UUID",
- "drupal_id": "Drupal ID",
- "image_url": "Image URL",
- }
-
- def get_farmos_url(self, obj):
- return None
-
- def get_template_context(self, context):
-
- if self.listing and self.farmos_refurl_path:
- context["farmos_refurl"] = self.app.get_farmos_url(self.farmos_refurl_path)
-
- return context
-
- def get_xref_buttons(self, obj):
- url = self.get_farmos_url(obj)
- if url:
- return [
- self.make_button(
- "View in farmOS",
- primary=True,
- url=url,
- target="_blank",
- icon_left="external-link-alt",
- )
- ]
- return []
diff --git a/src/wuttafarm/web/views/structure_types.py b/src/wuttafarm/web/views/structure_types.py
deleted file mode 100644
index ca85fb9..0000000
--- a/src/wuttafarm/web/views/structure_types.py
+++ /dev/null
@@ -1,118 +0,0 @@
-# -*- coding: utf-8; -*-
-################################################################################
-#
-# WuttaFarm --Web app to integrate with and extend farmOS
-# Copyright © 2026 Lance Edgar
-#
-# This file is part of WuttaFarm.
-#
-# WuttaFarm is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-#
-# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# WuttaFarm. If not, see .
-#
-################################################################################
-"""
-Master view for Structure Types
-"""
-
-from wuttafarm.db.model.structures import StructureType, Structure
-from wuttafarm.web.views import WuttaFarmMasterView
-
-
-class StructureTypeView(WuttaFarmMasterView):
- """
- Master view for Structure Types
- """
-
- model_class = StructureType
- route_prefix = "structure_types"
- url_prefix = "/structure-types"
-
- grid_columns = [
- "name",
- ]
-
- sort_defaults = "name"
-
- filter_defaults = {
- "name": {"active": True, "verb": "contains"},
- }
-
- form_fields = [
- "name",
- "farmos_uuid",
- "drupal_id",
- ]
-
- has_rows = True
- row_model_class = Structure
- rows_viewable = True
-
- row_grid_columns = [
- "name",
- "is_location",
- "is_fixed",
- "active",
- ]
-
- rows_sort_defaults = "name"
-
- def configure_grid(self, grid):
- g = grid
- super().configure_grid(g)
-
- # name
- g.set_link("name")
-
- def get_xref_buttons(self, structure_type):
- buttons = super().get_xref_buttons(structure_type)
-
- if structure_type.farmos_uuid:
- buttons.append(
- self.make_button(
- "View farmOS record",
- primary=True,
- url=self.request.route_url(
- "farmos_structure_types.view", uuid=structure_type.farmos_uuid
- ),
- icon_left="eye",
- )
- )
-
- return buttons
-
- def get_row_grid_data(self, structure_type):
- model = self.app.model
- session = self.Session()
- return session.query(model.Structure).filter(
- model.Structure.structure_type == structure_type
- )
-
- def configure_row_grid(self, grid):
- g = grid
- super().configure_row_grid(g)
-
- # name
- g.set_link("name")
-
- def get_row_action_url_view(self, structure, i):
- return self.request.route_url("structures.view", uuid=structure.uuid)
-
-
-def defaults(config, **kwargs):
- base = globals()
-
- StructureTypeView = kwargs.get("StructureTypeView", base["StructureTypeView"])
- StructureTypeView.defaults(config)
-
-
-def includeme(config):
- defaults(config)
diff --git a/src/wuttafarm/web/views/structures.py b/src/wuttafarm/web/views/structures.py
deleted file mode 100644
index df58fda..0000000
--- a/src/wuttafarm/web/views/structures.py
+++ /dev/null
@@ -1,127 +0,0 @@
-# -*- coding: utf-8; -*-
-################################################################################
-#
-# WuttaFarm --Web app to integrate with and extend farmOS
-# Copyright © 2026 Lance Edgar
-#
-# This file is part of WuttaFarm.
-#
-# WuttaFarm is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-#
-# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# WuttaFarm. If not, see .
-#
-################################################################################
-"""
-Master view for Structures
-"""
-
-from wuttafarm.db.model.structures import Structure
-from wuttafarm.web.views import WuttaFarmMasterView
-from wuttafarm.web.forms.schema import StructureTypeRef
-from wuttafarm.web.forms.widgets import ImageWidget
-
-
-class StructureView(WuttaFarmMasterView):
- """
- Master view for Structures
- """
-
- model_class = Structure
- route_prefix = "structures"
- url_prefix = "/structures"
-
- farmos_refurl_path = "/assets/structure"
-
- grid_columns = [
- "name",
- "structure_type",
- "is_location",
- "is_fixed",
- "active",
- ]
-
- sort_defaults = "name"
-
- filter_defaults = {
- "name": {"active": True, "verb": "contains"},
- }
-
- form_fields = [
- "name",
- "structure_type",
- "is_location",
- "is_fixed",
- "notes",
- "active",
- "farmos_uuid",
- "drupal_id",
- "image_url",
- "image",
- ]
-
- def configure_grid(self, grid):
- g = grid
- super().configure_grid(g)
- model = self.app.model
-
- # name
- g.set_link("name")
-
- # structure_type
- g.set_joiner("structure_type", lambda q: q.join(model.StructureType))
- g.set_sorter("structure_type", model.StructureType.name)
- g.set_filter(
- "structure_type", model.StructureType.name, label="Structure Type Name"
- )
-
- def configure_form(self, form):
- f = form
- super().configure_form(f)
- structure = form.model_instance
-
- # structure_type
- f.set_node("structure_type", StructureTypeRef(self.request))
-
- # image
- if structure.image_url:
- f.set_widget("image", ImageWidget("structure image"))
- f.set_default("image", structure.image_url)
-
- def get_farmos_url(self, structure):
- return self.app.get_farmos_url(f"/asset/{structure.drupal_id}")
-
- def get_xref_buttons(self, structure):
- buttons = super().get_xref_buttons(structure)
-
- if structure.farmos_uuid:
- buttons.append(
- self.make_button(
- "View farmOS record",
- primary=True,
- url=self.request.route_url(
- "farmos_structures.view", uuid=structure.farmos_uuid
- ),
- icon_left="eye",
- )
- )
-
- return buttons
-
-
-def defaults(config, **kwargs):
- base = globals()
-
- StructureView = kwargs.get("StructureView", base["StructureView"])
- StructureView.defaults(config)
-
-
-def includeme(config):
- defaults(config)
diff --git a/src/wuttafarm/web/views/users.py b/src/wuttafarm/web/views/users.py
deleted file mode 100644
index f35aef7..0000000
--- a/src/wuttafarm/web/views/users.py
+++ /dev/null
@@ -1,99 +0,0 @@
-# -*- coding: utf-8; -*-
-################################################################################
-#
-# WuttaFarm --Web app to integrate with and extend farmOS
-# Copyright © 2026 Lance Edgar
-#
-# This file is part of WuttaFarm.
-#
-# WuttaFarm is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, either version 3 of the License, or (at your option) any later
-# version.
-#
-# WuttaFarm is distributed in the hope that it will be useful, but WITHOUT ANY
-# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# WuttaFarm. If not, see .
-#
-################################################################################
-"""
-Views for Users
-"""
-
-from wuttaweb.views import users as base
-
-
-class UserView(base.UserView):
- """
- Custom master view for Users.
- """
-
- labels = {
- "farmos_uuid": "farmOS UUID",
- "drupal_id": "Drupal ID",
- }
-
- def get_template_context(self, context):
- context = super().get_template_context(context)
-
- if self.listing:
- context["farmos_refurl"] = self.app.get_farmos_url("/admin/people")
-
- return context
-
- def configure_form(self, form):
- """ """
- f = form
- super().configure_form(f)
- user = f.model_instance
-
- # farmos_uuid
- if not self.creating:
- f.fields.append("farmos_uuid")
- f.set_default("farmos_uuid", user.farmos_uuid)
-
- # drupal_id
- if not self.creating:
- f.fields.append("drupal_id")
- f.set_default("drupal_id", user.drupal_id)
-
- def get_xref_buttons(self, user):
- buttons = []
-
- if user.drupal_id:
- buttons.append(
- self.make_button(
- "View in farmOS",
- primary=True,
- url=self.app.get_farmos_url(f"/user/{user.drupal_id}"),
- target="_blank",
- icon_left="external-link-alt",
- )
- )
-
- if user.farmos_uuid:
- buttons.append(
- self.make_button(
- "View farmOS record",
- primary=True,
- url=self.request.route_url(
- "farmos_users.view", uuid=user.farmos_uuid
- ),
- icon_left="eye",
- )
- )
-
- return buttons
-
-
-def defaults(config, **kwargs):
- local = globals()
- UserView = kwargs.get("UserView", local["UserView"])
- base.defaults(config, **{"UserView": UserView})
-
-
-def includeme(config):
- defaults(config)