Compare commits

..

No commits in common. "master" and "v0.1.0" have entirely different histories.

197 changed files with 137 additions and 24162 deletions

3
.gitignore vendored
View file

@ -1,6 +1,3 @@
*~
*.pyc
dist/
docs/_build/
style/dist/
style/node_modules/

View file

@ -5,251 +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.8.0 (2026-03-04)
### Feat
- improve support for exporting quantity, log data
- show related Quantity records when viewing a Measure
- show related Quantity records when viewing a Unit
- show link to Log record when viewing Quantity
### Fix
- bump version requirement for wuttaweb
## v0.7.0 (2026-03-04)
### Feat
- expose "group membership" for assets
- expose "current location" for assets
- add schema, sync support for `Log.is_movement`
- add schema, import support for `Asset.owners`
- add schema, import support for `Log.quick`
- show quantities when viewing log
- add sync support for `MedicalLog.vet`
- add schema, import support for `Log.quantities`
- add schema, import support for `Log.groups`
- add schema, import support for `Log.locations`
- add sync support for `Log.is_group_assignment`
- add support for exporting log status, timestamp to farmOS
- add support for log 'owners'
- add support for edit, import/export of plant type data
- add way to create animal type when editing animal
- add related version tables for asset/log revision history
- improve mirror/deletion for assets, logs, animal types
- auto-delete asset from farmOS if deleting via mirror app
### Fix
- show drupal ID column for asset types
- remove unique constraint for `LandAsset.land_type_uuid`
- move farmOS UUID field below the Drupal ID
- add links for Parents column in All Assets grid
- set timestamp for new log in quick eggs form
- set default grid pagesize to 50
- add placeholder for log 'quick' field
- define log grid columns to match farmOS
- make AllLogView inherit from LogMasterView
- rename views for "all records" (all assets, all logs etc.)
- ensure token refresh works regardless where API client is used
- render links for Plant Type column in Plant Assets grid
- fix land asset type
- prevent edit for asset types, land types when app is mirror
- add farmOS-style links for Parents column in Land Assets grid
- remove unique constraint for `AnimalType.name`
- prevent delete if animal type is still being referenced
- add reminder to restart if changing integration mode
- prevent edit for user farmos_uuid, drupal_id
- remove 'contains' verb for sex filter
- add enum, row hilite for log status
- fix Sex field when empty and deleting an animal
- add `get_farmos_client_for_user()` convenience function
- use current user token for auto-sync within web app
- set log type, status enums for log grids
- add more default perms for first site admin user
- only show quick form menu if perms allow
- expose config for farmOS OAuth2 client_id and scope
- add separate permission for each quick form view
## v0.6.0 (2026-02-25)
### Feat
- add common normalizer to simplify code in view, importer etc.
- overhaul farmOS log views; add Eggs quick form
- add basic CRUD for direct API views: animal types, animal assets
- use 'include' API param for better Animal Assets grid data
- add backend filters, sorting for farmOS animal types, assets
- include/exclude certain views, menus based on integration mode
- add Standard Quantities table, views, import
- add Quantity Types table, views, import
- add Units table, views, import/export
### Fix
- add `Notes` schema type
- add grid filter for animal birthdate
- add thumbnail to farmOS asset base view
- add setting to toggle "farmOS-style grid links"
- standardize a bit more for the farmOS Animal Assets view
- set *default* instead of configured menu handler
- expose farmOS integration mode, URL in app settings
- reword some menu entries
- add WuttaFarm -> farmOS export for Plant Assets
- fix default admin user perms, per new log schema
## v0.5.0 (2026-02-18)
### Feat
- add `produces_eggs` flag for animal, group assets
- add more assets (plant) and logs (harvest, medical, observation)
- refactor log models, views to use generic/common base
### Fix
- rename db model modules, for better convention
- add override for requests cert validation
## v0.4.1 (2026-02-17)
### Fix
- remove `AnimalType.changed` column
## v0.4.0 (2026-02-17)
### Feat
- add basic support for WuttaFarm → farmOS export
- convert group assets to use common base/mixin
- convert structure assets to use common base/mixin
- convert land assets to use common base/mixin
- add "generic" assets, new animal assets based on that
### Fix
- misc. field tweaks for asset forms
- show warning when viewing an archived asset
- fix some perms for all assets view
- fix initial admin perms per route renaming
- add parent relationships support for land assets
- cleanup Land views to better match farmOS
- cleanup Structure views to better match farmOS
- cleanup Group views to better match farmOS
- add / display thumbnail image for animals
- improve handling of 'archived' records for grid/form views
- use Male/Female dict enum for animal sex field
- prevent direct edit of `farmos_uuid` and `drupal_id` fields
- use same datetime display format as farmOS
- convert `active` flag to `archived`
- suppress output when user farmos/drupal keys are empty
- customize page footer to mention farmOS
## v0.3.1 (2026-02-14)
### Fix
- update sterile, archived flags per farmOS 4.x
## 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
- add custom (built) buefy css to repo
## v0.2.2 (2026-02-08)
### Fix
- update project links for PyPI
## v0.2.1 (2026-02-08)
### Fix
- run web app via uvicorn/ASGI by default
## v0.2.0 (2026-02-08)
### Feat
- add view for farmOS activity logs
- add view for farmOS log types
- add view for farmOS structure types
- add view for farmOS land types
- add view for farmOS land assets
- add view for farmOS groups
- add view for farmOS asset types
- add view for farmOS structures
- add view for farmOS animal types
- add view for farmOS users
### Fix
- add pyramid_exclog dependency
- add menu option, "Go to farmOS"
- ensure Buefy version matches what we use for custom css
## v0.1.5 (2026-02-07)
### Fix
- fix built wheel to include custom buefy css
## v0.1.4 (2026-02-07)
### Fix
- add custom style to better match farmOS color scheme
## v0.1.3 (2026-02-06)
### Fix
- fix a couple more edge cases around oauth2 token refresh
## v0.1.2 (2026-02-06)
### Fix
- add support for farmOS/OAuth2 Authorization Code grant/workflow
## v0.1.1 (2026-02-05)
### Fix
- preserve oauth2 token so auto-refresh works correctly
- customize app installer to configure farmos_url
- add some more info when viewing animal
- require minimum version for wuttaweb
## v0.1.0 (2026-02-03)
### Feat

View file

@ -13,4 +13,14 @@ include:
- possibly add more schema / extra features
- possibly sync data back to farmOS
See full docs at https://docs.wuttaproject.org/wuttafarm/
## Quick Start
Make a virtual environment and install the app:
python3 -m venv .venv
.venv/bin/pip install -e .
.venv/bin/wuttafarm install
For more info see
https://docs.wuttaproject.org/wuttjamaican/narr/install/index.html

View file

@ -1,20 +0,0 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

View file

View file

@ -1,6 +0,0 @@
``wuttafarm.app``
=================
.. automodule:: wuttafarm.app
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.auth``
==================
.. automodule:: wuttafarm.auth
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.cli.base``
======================
.. automodule:: wuttafarm.cli.base
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.cli.import_farmos``
===============================
.. automodule:: wuttafarm.cli.import_farmos
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.cli.install``
=========================
.. automodule:: wuttafarm.cli.install
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.cli``
=================
.. automodule:: wuttafarm.cli
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.config``
====================
.. automodule:: wuttafarm.config
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.db.model``
======================
.. automodule:: wuttafarm.db.model
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.db``
================
.. automodule:: wuttafarm.db
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.farmos.handler``
============================
.. automodule:: wuttafarm.farmos.handler
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.farmos``
====================
.. automodule:: wuttafarm.farmos
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.importing.farmos``
==============================
.. automodule:: wuttafarm.importing.farmos
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.importing``
=======================
.. automodule:: wuttafarm.importing
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.install``
=====================
.. automodule:: wuttafarm.install
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm``
=============
.. automodule:: wuttafarm
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.web.app``
=====================
.. automodule:: wuttafarm.web.app
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.web.forms``
=======================
.. automodule:: wuttafarm.web.forms
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.web.forms.schema``
==============================
.. automodule:: wuttafarm.web.forms.schema
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.web.forms.widgets``
===============================
.. automodule:: wuttafarm.web.forms.widgets
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.web.menus``
=======================
.. automodule:: wuttafarm.web.menus
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.web``
=================
.. automodule:: wuttafarm.web
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.web.static``
========================
.. automodule:: wuttafarm.web.static
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.web.subscribers``
=============================
.. automodule:: wuttafarm.web.subscribers
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.web.util``
======================
.. automodule:: wuttafarm.web.util
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.web.views.auth``
============================
.. automodule:: wuttafarm.web.views.auth
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.web.views.common``
==============================
.. automodule:: wuttafarm.web.views.common
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.web.views.farmos.animal_types``
===========================================
.. automodule:: wuttafarm.web.views.farmos.animal_types
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.web.views.farmos.animals``
======================================
.. automodule:: wuttafarm.web.views.farmos.animals
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.web.views.farmos.asset_types``
==========================================
.. automodule:: wuttafarm.web.views.farmos.asset_types
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.web.views.farmos.groups``
=====================================
.. automodule:: wuttafarm.web.views.farmos.groups
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.web.views.farmos.land_assets``
==========================================
.. automodule:: wuttafarm.web.views.farmos.land_assets
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.web.views.farmos.land_types``
=========================================
.. automodule:: wuttafarm.web.views.farmos.land_types
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.web.views.farmos.log_types``
========================================
.. automodule:: wuttafarm.web.views.farmos.log_types
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.web.views.farmos.logs_activity``
============================================
.. automodule:: wuttafarm.web.views.farmos.logs_activity
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.web.views.farmos.master``
=====================================
.. automodule:: wuttafarm.web.views.farmos.master
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.web.views.farmos``
==============================
.. automodule:: wuttafarm.web.views.farmos
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.web.views.farmos.structure_types``
==============================================
.. automodule:: wuttafarm.web.views.farmos.structure_types
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.web.views.farmos.structures``
=========================================
.. automodule:: wuttafarm.web.views.farmos.structures
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.web.views.farmos.users``
====================================
.. automodule:: wuttafarm.web.views.farmos.users
:members:

View file

@ -1,6 +0,0 @@
``wuttafarm.web.views``
=======================
.. automodule:: wuttafarm.web.views
:members:

View file

@ -1,40 +0,0 @@
# Configuration file for the Sphinx documentation builder.
#
# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
from importlib.metadata import version as get_version
project = "WuttaFarm"
copyright = "2026, Lance Edgar"
author = "Lance Edgar"
release = get_version("WuttaFarm")
# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
extensions = [
"sphinx.ext.autodoc",
"sphinx.ext.intersphinx",
"sphinx.ext.viewcode",
"sphinx.ext.todo",
"sphinxcontrib.programoutput",
]
templates_path = ["_templates"]
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
intersphinx_mapping = {
"wuttjamaican": ("https://docs.wuttaproject.org/wuttjamaican/", None),
"wutta-continuum": ("https://docs.wuttaproject.org/wutta-continuum/", None),
}
# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
html_theme = "furo"
html_static_path = ["_static"]

View file

@ -1,84 +0,0 @@
WuttaFarm
=========
This is a Python web app (built with `WuttaWeb`_), to integrate with
and extend `farmOS`_.
.. _WuttaWeb: https://wuttaproject.org
.. _farmOS: https://farmos.org
It is just an experiment so far; the ideas I hope to play with
include:
- display farmOS data directly, via real-time API fetch
- add "mirror" schema and sync data from farmOS to app DB (and display it)
- 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
:caption: Documentation:
narr/install
narr/auth
narr/features
narr/cli
.. toctree::
:maxdepth: 1
:caption: Package API:
api/wuttafarm
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
api/wuttafarm.web.forms
api/wuttafarm.web.forms.schema
api/wuttafarm.web.forms.widgets
api/wuttafarm.web.menus
api/wuttafarm.web.static
api/wuttafarm.web.subscribers
api/wuttafarm.web.util
api/wuttafarm.web.views
api/wuttafarm.web.views.auth
api/wuttafarm.web.views.common
api/wuttafarm.web.views.farmos
api/wuttafarm.web.views.farmos.animals
api/wuttafarm.web.views.farmos.animal_types
api/wuttafarm.web.views.farmos.asset_types
api/wuttafarm.web.views.farmos.groups
api/wuttafarm.web.views.farmos.land_assets
api/wuttafarm.web.views.farmos.land_types
api/wuttafarm.web.views.farmos.logs_activity
api/wuttafarm.web.views.farmos.log_types
api/wuttafarm.web.views.farmos.master
api/wuttafarm.web.views.farmos.structures
api/wuttafarm.web.views.farmos.structure_types
api/wuttafarm.web.views.farmos.users
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

View file

@ -1,35 +0,0 @@
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=.
set BUILDDIR=_build
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.https://www.sphinx-doc.org/
exit /b 1
)
if "%1" == "" goto help
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
:end
popd

View file

@ -1,58 +0,0 @@
==============
Authentication
==============
At the moment, the expected user login process is as follows:
First Launch
------------
When you first visit the app, it will not have any user accounts so
you will be shown a form to create one.
The username should ideally match your main (daily driver) username
within farmOS. The password you give can be anything though, does not
need to (and perhaps should not) match farmOS.
This account will belong to the Administrator role within WuttaFarm,
which means it can "become root" (same concept as ``sudo`` basically).
Once the account is created you will be shown the normal login page.
Go ahead and login with this account using the username and password
you gave it. But then you should logout again, for the next step.
OAuth2
------
The assumption (for now) is that users will login via farmOS / OAuth2
for normal operations. Doing so will embed the access token within
the WuttaFarm app user session, which means the user can actually
browse farmOS data within the WuttaFarm views.
.. note::
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.)
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
login to farmOS (if you're not already) and if you wish to grant
access to the 3rd party app (WuttaFarm; if you didn't already).
If all goes well you should be back in WuttaFarm, logged in as the
same username you have in farmOS.
Note that your first admin user in WuttaFarm ideally *should* have the
same username as farmOS, but regardless when you login via OAuth2, a
user account will be automatically created if necessary in WuttaFarm,
with that same username.

View file

@ -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

View file

@ -1,122 +0,0 @@
========
Features
========
Here is the list of features currently supported:
* login via farmOS / OAuth2 workflows
* Authorization Code workflow is supported
* (technically, Password Grant workflow is also supported, for now)
* view some farmOS data directly
* limited data is fetched via farmOS API for several views
* 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)
* export some data back to farmOS
* limited data is exported back via farmOS API, from native tables
* supported tables are auto-synced when a record is created/updated
* AnimalType
* AnimalAsset
* GroupAsset
* LandAsset
* StructureAsset
How I Use This App
------------------
My production farmOS instance is deployed via Podman container, which
I prefer over Docker. (Not that I know much about any of that
really.) It has a PostgreSQL database which runs in a separate
container.
My production WuttaFarm instance is installed directly on the same
host machine, in a Python virtual environment. PostgreSQL is also
installed on the host machine; the app uses that for DB.
I ran the initial "special" import to establish the user accounts;
then I ran the "full" import (farmOS → WuttaFarm). See also
:doc:`/narr/install`.
I configured a cron job to run the full import every night, but in
dry-run mode with warnings. This means I will get an email if
WuttaFarm is ever out of sync with farmOS.
With all that in place, I can use WuttaFarm as my "daily driver" to
add/edit assets (and soon, logs). Changes I make are immediately
synced to farmOS, so as long as the overnight check does not send me
an email, I know everything is good.
Roadmap
-------
Here are some things I still have planned so far:
* finish support for auto-sync, in current asset models
* must make "asset parents" editable
* add more asset models?
* i may only add those i need for now, but others can add more
* flesh out the log model support
* add more tables, fields to schema
* add/improve import and export
* basically this should be as good as the asset model support
* although again i may only add those i need for now
* add custom "quick forms" for assets and logs
* again i probably will just add a few (e.g. egg collection)
* but this could be an interesting path to go down, we'll see
* add custom "CSV/file importers"
* the framework has some pretty neat tools around this, so..
* ..even if i don't need CSV import i'd like to show what's possible
Notably **off the table** for now are:
* anything involving maps
* file/image attachments
I will just import "thumbnail" and "large" image URLs from farmOS for
each asset for now. Will have to think more on the image/attachment
stuff before I'll know if/how to add support in WuttaFarm.
Maps will wait mostly because I have never done anything involving
those (or GIS etc. - if that's even the right term). And anyway the
main "use" for this app is probably around data entry, so it may never
"need" maps support.
Screenshots
-----------
Login Screen
~~~~~~~~~~~~
.. image:: https://wuttaproject.org/images/wuttafarm/screenshot001.png
List All Assets
~~~~~~~~~~~~~~~
.. image:: https://wuttaproject.org/images/wuttafarm/screenshot002.png
View Animal Asset
~~~~~~~~~~~~~~~~~
.. image:: https://wuttaproject.org/images/wuttafarm/screenshot003.png
Edit Animal Asset
~~~~~~~~~~~~~~~~~
.. image:: https://wuttaproject.org/images/wuttafarm/screenshot004.png

View file

@ -1,185 +0,0 @@
==============
Installation
==============
For now, these instructions mostly reflect my own dev workflow. It
uses a Python virtual environment but no (Docker) containers.
Eventually it may make sense to add production deployment steps using
Docker etc. - but that will wait for now.
Requirements
------------
WuttaFarm is designed to run on a (Debian-based) Linux machine; YMMV
with others.
farmOS
~~~~~~
First you must have a *production* `farmOS`_ instance running
somewhere. For more on that see `Hosting farmOS`_.
.. _farmOS: https://farmos.org
.. _Hosting farmOS: https://farmos.org/hosting/
This must use HTTPS for the OAuth2 workflows to work correctly. (Not
sure but it may also need to be at the root of the domain, i.e. no
subpath.)
Database
~~~~~~~~
You also must create a PostgreSQL (or MySQL) database for the
WuttaFarm app to use. See also :ref:`wuttjamaican:create-appdb`.
App Setup
---------
The short version:
.. code-block:: sh
python3 -m venv ./venv
./venv/bin/pip install WuttaFarm
./venv/bin/wuttafarm install
The app installer (last command above) will prompt you for DB
credentials, and the farmOS URL.
One of the questions is about data versioning with
:doc:`wutta-continuum:index`. You should probaby enable that even
though as of writing the default is disabled. It adds "revision
history" for most types of records in the WuttaFarm app DB.
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
Email Setup
-----------
WuttaFarm can send emails of various kinds; of note are:
* when user submits Feedback via button in top right of screen
* importer diff warning for farmOS → WuttaFarm
That last one is optional, triggered via the ``-W`` flag in the
importer command line.
Anyway the app basically assumes there is a Postfix or similar mail
server running on "localhost" which it can use as the SMTP server, and
which is in turn responsible for "really" sending the email out via
some configured relay. This has always worked very well for me since
I tend to want to have email working for other reasons on each Linux
server I maintain. (And since I have not traditionally used Docker
and/or containers.)
So if you need something else, touch base and we'll figure something
out. But assuming localhost is okay to use:
In the web app menu, see Admin -> App Info and then click Configure.
Check the box to enable email and plug in the default sender and
recipient (which should be the admin responsible for the app). I
often create an alias so I can use e.g. wuttafarm@edbob.org as
sender - aliased back to myself in case it generates bounces so I can
see them.
From there you can also see Admin -> Email Settings in the menu; this
lets you control and preview each type of email separately.
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

View file

@ -5,7 +5,7 @@ build-backend = "hatchling.build"
[project]
name = "WuttaFarm"
version = "0.8.0"
version = "0.1.0"
description = "Web app to integrate with and extend farmOS"
readme = "README.md"
authors = [
@ -31,42 +31,28 @@ license = {text = "GNU General Public License v3"}
dependencies = [
"farmOS",
"psycopg2",
"pyramid_exclog",
"uvicorn[standard]",
"WuttaSync",
"WuttaWeb[continuum]>=0.29.0",
"WuttaWeb[continuum]",
]
[project.optional-dependencies]
docs = ["Sphinx", "furo", "sphinxcontrib-programoutput"]
[project.scripts]
"wuttafarm" = "wuttafarm.cli:wuttafarm_typer"
[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"]
"export.to_farmos.from_wuttafarm" = "wuttafarm.farmos.importing.wuttafarm:FromWuttaFarmToFarmOS"
"import.to_wuttafarm.from_farmos" = "wuttafarm.importing.farmos:FromFarmOSToWuttaFarm"
[project.urls]
Homepage = "https://forgejo.wuttaproject.org/wutta/wuttafarm"
Repository = "https://forgejo.wuttaproject.org/wutta/wuttafarm"
Issues = "https://forgejo.wuttaproject.org/wutta/wuttafarm/issues"
Changelog = "https://forgejo.wuttaproject.org/wutta/wuttafarm/src/branch/master/CHANGELOG.md"
Homepage = "https://forgejo.wuttaproject.org/lance/wuttafarm"
Repository = "https://forgejo.wuttaproject.org/lance/wuttafarm"
Issues = "https://forgejo.wuttaproject.org/lance/wuttafarm/issues"
Changelog = "https://forgejo.wuttaproject.org/lance/wuttafarm/src/branch/master/CHANGELOG.md"
[tool.commitizen]
@ -76,8 +62,3 @@ update_changelog_on_bump = true
[tool.hatch.build.targets.wheel]
packages = ["src/wuttafarm"]
[tool.hatch.build.targets.sdist]
exclude = [
"style/node_modules/",
]

View file

@ -31,25 +31,7 @@ class WuttaFarmAppHandler(base.AppHandler):
Custom :term:`app handler` for WuttaFarm.
"""
display_format_datetime = "%a, %m/%d/%Y - %H:%M"
default_auth_handler_spec = "wuttafarm.auth:WuttaFarmAuthHandler"
default_install_handler_spec = "wuttafarm.install:WuttaFarmInstallHandler"
def get_asset_handler(self):
"""
Get the configured asset handler.
:rtype: :class:`~wuttafarm.assets.AssetHandler`
"""
if "asset" not in self.handlers:
spec = self.config.get(
f"{self.appname}.asset_handler",
default="wuttafarm.assets:AssetHandler",
)
factory = self.load_object(spec)
self.handlers["asset"] = factory(self.config)
return self.handlers["asset"]
def get_farmos_handler(self):
"""
@ -60,167 +42,16 @@ class WuttaFarmAppHandler(base.AppHandler):
if "farmos" not in self.handlers:
spec = self.config.get(
f"{self.appname}.farmos_handler",
default="wuttafarm.farmos.handler:FarmOSHandler",
default="wuttafarm.farmos:FarmOSHandler",
)
factory = self.load_object(spec)
self.handlers["farmos"] = factory(self.config)
return self.handlers["farmos"]
def get_farmos_integration_mode(self):
"""
Returns the integration mode for farmOS, i.e. to control the
app's behavior regarding that.
"""
enum = self.enum
return self.config.get(
f"{self.appname}.farmos_integration_mode",
default=enum.FARMOS_INTEGRATION_MODE_WRAPPER,
)
def is_farmos_mirror(self):
"""
Returns ``True`` if the app is configured in "mirror"
integration mode with regard to farmOS.
"""
enum = self.enum
mode = self.get_farmos_integration_mode()
return mode == enum.FARMOS_INTEGRATION_MODE_MIRROR
def is_farmos_wrapper(self):
"""
Returns ``True`` if the app is configured in "wrapper"
integration mode with regard to farmOS.
"""
enum = self.enum
mode = self.get_farmos_integration_mode()
return mode == enum.FARMOS_INTEGRATION_MODE_WRAPPER
def is_standalone(self):
"""
Returns ``True`` if the app is configured in "standalone" mode
with regard to farmOS.
"""
enum = self.enum
mode = self.get_farmos_integration_mode()
return mode == enum.FARMOS_INTEGRATION_MODE_NONE
def get_farmos_url(self, *args, **kwargs):
"""
Get a farmOS URL. This is a convenience wrapper around
:meth:`~wuttafarm.farmos.handler.FarmOSHandler.get_farmos_url()`.
:meth:`~wuttafarm.farmos.FarmOSHandler.get_farmos_url()`.
"""
handler = self.get_farmos_handler()
return handler.get_farmos_url(*args, **kwargs)
def get_farmos_client(self, *args, **kwargs):
"""
Get a farmOS client. This is a convenience wrapper around
:meth:`~wuttafarm.farmos.handler.FarmOSHandler.get_farmos_client()`.
"""
handler = self.get_farmos_handler()
return handler.get_farmos_client(*args, **kwargs)
def is_farmos_3x(self, *args, **kwargs):
"""
Check if the farmOS version is 3.x. This is a convenience
wrapper around
:meth:`~wuttafarm.farmos.handler.FarmOSHandler.is_farmos_3x()`.
"""
handler = self.get_farmos_handler()
return handler.is_farmos_3x(*args, **kwargs)
def is_farmos_4x(self, *args, **kwargs):
"""
Check if the farmOS version is 4.x. This is a convenience
wrapper around
:meth:`~wuttafarm.farmos.handler.FarmOSHandler.is_farmos_4x()`.
"""
handler = self.get_farmos_handler()
return handler.is_farmos_4x(*args, **kwargs)
def get_normalizer(self, farmos_client=None):
"""
Get the configured farmOS integration handler.
:rtype: :class:`~wuttafarm.farmos.FarmOSHandler`
"""
spec = self.config.get(
f"{self.appname}.normalizer_spec",
default="wuttafarm.normal:Normalizer",
)
factory = self.load_object(spec)
return factory(self.config, farmos_client)
def auto_sync_to_farmos(self, obj, model_name=None, client=None, require=True):
"""
Export the given object to farmOS, using configured handler.
This should ensure the given object is also *updated* with the
farmOS UUID and Drupal ID, when new record is created in
farmOS.
:param obj: Any data object in WuttaFarm, e.g. AnimalAsset
instance.
:param client: Existing farmOS API client to use. If not
specified, a new one will be instantiated.
:param require: If true, this will *require* the export
handler to support objects of the given type. If false,
then nothing will happen / export is silently skipped when
there is no such exporter.
"""
handler = self.app.get_import_handler("export.to_farmos.from_wuttafarm")
if not model_name:
model_name = type(obj).__name__
if model_name not in handler.importers:
if require:
raise ValueError(f"no exporter found for {model_name}")
return
# nb. begin txn to establish the API client
handler.begin_target_transaction(client)
importer = handler.get_importer(model_name, caches_target=False)
normal = importer.normalize_source_object(obj)
importer.process_data(source_data=[normal])
def auto_sync_from_farmos(self, obj, model_name, client=None, require=True):
"""
Import the given object from farmOS, using configured handler.
:param obj: Any data record from farmOS.
:param model_name': Model name for the importer to use,
e.g. ``"AnimalAsset"``.
:param client: Existing farmOS API client to use. If not
specified, a new one will be instantiated.
:param require: If true, this will *require* the import
handler to support objects of the given type. If false,
then nothing will happen / import is silently skipped when
there is no such importer.
"""
handler = self.app.get_import_handler("import.to_wuttafarm.from_farmos")
if model_name not in handler.importers:
if require:
raise ValueError(f"no importer found for {model_name}")
return
# nb. begin txn to establish the API client
handler.begin_source_transaction(client)
with self.short_session(commit=True) as session:
handler.target_session = session
importer = handler.get_importer(model_name, caches_target=False)
normal = importer.normalize_source_object(obj)
importer.process_data(source_data=[normal])
class WuttaFarmAppProvider(base.AppProvider):
"""
The :term:`app provider` for WuttaFarm.
"""
email_modules = ["wuttafarm.emails"]

View file

@ -1,65 +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 <http://www.gnu.org/licenses/>.
#
################################################################################
"""
Asset handler
"""
from wuttjamaican.app import GenericHandler
class AssetHandler(GenericHandler):
"""
Base class and default implementation for the asset
:term:`handler`.
"""
def get_groups(self, asset):
model = self.app.model
session = self.app.get_session(asset)
grplog = (
session.query(model.Log)
.join(model.LogAsset)
.filter(model.LogAsset.asset == asset)
.filter(model.Log.is_group_assignment == True)
.order_by(model.Log.timestamp.desc())
.first()
)
if grplog:
return grplog.groups
return []
def get_locations(self, asset):
model = self.app.model
session = self.app.get_session(asset)
loclog = (
session.query(model.Log)
.join(model.LogAsset)
.filter(model.LogAsset.asset == asset)
.filter(model.Log.is_movement == True)
.order_by(model.Log.timestamp.desc())
.first()
)
if loclog:
return loclog.locations
return []

View file

@ -25,6 +25,7 @@ Auth handler for use with farmOS
from uuid import UUID
from farmOS import farmOS
from oauthlib.oauth2.rfc6749.errors import InvalidGrantError
from sqlalchemy import orm
@ -88,7 +89,8 @@ class WuttaFarmAuthHandler(AuthHandler):
return None
def get_farmos_oauth2_token(self, username, password):
client = self.app.get_farmos_client()
url = self.app.get_farmos_url()
client = farmOS(url)
try:
return client.authorize(username=username, password=password)
except InvalidGrantError:

View file

@ -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()

View file

@ -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 <http://www.gnu.org/licenses/>.
#
################################################################################
"""
WuttaFarm CLI
"""
from .base import wuttafarm_typer
# nb. must bring in all modules for discovery to work
from . import export_farmos
from . import import_farmos
from . import install

View file

@ -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 <http://www.gnu.org/licenses/>.
#
################################################################################
"""
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"
)

View file

@ -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 <http://www.gnu.org/licenses/>.
#
################################################################################
"""
See also: :ref:`wuttafarm-export-farmos`
"""
import typer
from wuttasync.cli import import_command, ImportCommandHandler
from wuttafarm.cli import wuttafarm_typer
@wuttafarm_typer.command()
@import_command
def export_farmos(ctx: typer.Context, **kwargs):
"""
Export data from WuttaFarm to farmOS API
"""
config = ctx.parent.wutta_config
handler = ImportCommandHandler(config, key="export.to_farmos.from_wuttafarm")
handler.run(ctx)

View file

@ -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 <http://www.gnu.org/licenses/>.
#
################################################################################
"""
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)

View file

@ -23,8 +23,6 @@
WuttaFarm config extensions
"""
import os
from wuttjamaican.conf import WuttaConfigExtension
@ -41,26 +39,19 @@ class WuttaFarmConfig(WuttaConfigExtension):
config.setdefault(f"{config.appname}.app_title", "WuttaFarm")
config.setdefault(f"{config.appname}.app_dist", "WuttaFarm")
# app model/enum
# app model
config.setdefault(f"{config.appname}.model_spec", "wuttafarm.db.model")
config.setdefault(f"{config.appname}.enum_spec", "wuttafarm.enum")
# app handler
config.setdefault(
f"{config.appname}.app.handler", "wuttafarm.app:WuttaFarmAppHandler"
)
# web app stuff
# web app menu
config.setdefault(
f"{config.appname}.web.menus.handler.default_spec",
f"{config.appname}.web.menus.handler.spec",
"wuttafarm.web.menus:WuttaFarmMenuHandler",
)
config.setdefault("wuttaweb.grids.default_pagesize", "50")
# web app libcache
# config.setdefault('wuttaweb.static_libcache.module', 'wuttafarm.web.static')
# maybe override cert validation for requests lib.
# nb. this is "global" and not "specific" to the farmos API requests!
if bundle := config.get(f"{config.appname}.requests_ca_bundle"):
os.environ.setdefault("REQUESTS_CA_BUNDLE", bundle)

View file

@ -1,37 +0,0 @@
"""add Log.is_movement
Revision ID: 0771322957bd
Revises: 12de43facb95
Create Date: 2026-03-02 20:21:03.889847
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
import wuttjamaican.db.util
# revision identifiers, used by Alembic.
revision: str = "0771322957bd"
down_revision: Union[str, None] = "12de43facb95"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# log
op.add_column("log", sa.Column("is_movement", sa.Boolean(), nullable=True))
op.add_column(
"log_version",
sa.Column("is_movement", sa.Boolean(), autoincrement=False, nullable=True),
)
def downgrade() -> None:
# log
op.drop_column("log_version", "is_movement")
op.drop_column("log", "is_movement")

View file

@ -1,596 +0,0 @@
"""add Plant Assets and more Logs
Revision ID: 11e0e46f48a6
Revises: dd6351e69233
Create Date: 2026-02-18 18:11:46.536930
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
import wuttjamaican.db.util
# revision identifiers, used by Alembic.
revision: str = "11e0e46f48a6"
down_revision: Union[str, None] = "dd6351e69233"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# plant_type
op.create_table(
"plant_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.Integer(), nullable=True),
sa.PrimaryKeyConstraint("uuid", name=op.f("pk_plant_type")),
sa.UniqueConstraint("drupal_id", name=op.f("uq_plant_type_drupal_id")),
sa.UniqueConstraint("farmos_uuid", name=op.f("uq_plant_type_farmos_uuid")),
sa.UniqueConstraint("name", name=op.f("uq_plant_type_name")),
)
op.create_table(
"plant_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_plant_type_version")
),
)
op.create_index(
op.f("ix_plant_type_version_end_transaction_id"),
"plant_type_version",
["end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_plant_type_version_operation_type"),
"plant_type_version",
["operation_type"],
unique=False,
)
op.create_index(
"ix_plant_type_version_pk_transaction_id",
"plant_type_version",
["uuid", sa.literal_column("transaction_id DESC")],
unique=False,
)
op.create_index(
"ix_plant_type_version_pk_validity",
"plant_type_version",
["uuid", "transaction_id", "end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_plant_type_version_transaction_id"),
"plant_type_version",
["transaction_id"],
unique=False,
)
# asset_plant
op.create_table(
"asset_plant",
sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.ForeignKeyConstraint(
["uuid"], ["asset.uuid"], name=op.f("fk_asset_plant_uuid_asset")
),
sa.PrimaryKeyConstraint("uuid", name=op.f("pk_asset_plant")),
)
op.create_table(
"asset_plant_version",
sa.Column(
"uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
),
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_plant_version")
),
)
op.create_index(
op.f("ix_asset_plant_version_end_transaction_id"),
"asset_plant_version",
["end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_asset_plant_version_operation_type"),
"asset_plant_version",
["operation_type"],
unique=False,
)
op.create_index(
"ix_asset_plant_version_pk_transaction_id",
"asset_plant_version",
["uuid", sa.literal_column("transaction_id DESC")],
unique=False,
)
op.create_index(
"ix_asset_plant_version_pk_validity",
"asset_plant_version",
["uuid", "transaction_id", "end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_asset_plant_version_transaction_id"),
"asset_plant_version",
["transaction_id"],
unique=False,
)
# asset_plant_plant_type
op.create_table(
"asset_plant_plant_type",
sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.Column("plant_asset_uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.Column("plant_type_uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.ForeignKeyConstraint(
["plant_asset_uuid"],
["asset_plant.uuid"],
name=op.f("fk_asset_plant_plant_type_plant_asset_uuid_asset_plant"),
),
sa.ForeignKeyConstraint(
["plant_type_uuid"],
["plant_type.uuid"],
name=op.f("fk_asset_plant_plant_type_plant_type_uuid_plant_type"),
),
sa.PrimaryKeyConstraint("uuid", name=op.f("pk_asset_plant_plant_type")),
)
op.create_table(
"asset_plant_plant_type_version",
sa.Column(
"uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
),
sa.Column(
"plant_asset_uuid",
wuttjamaican.db.util.UUID(),
autoincrement=False,
nullable=True,
),
sa.Column(
"plant_type_uuid",
wuttjamaican.db.util.UUID(),
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_plant_plant_type_version")
),
)
op.create_index(
op.f("ix_asset_plant_plant_type_version_end_transaction_id"),
"asset_plant_plant_type_version",
["end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_asset_plant_plant_type_version_operation_type"),
"asset_plant_plant_type_version",
["operation_type"],
unique=False,
)
op.create_index(
"ix_asset_plant_plant_type_version_pk_transaction_id",
"asset_plant_plant_type_version",
["uuid", sa.literal_column("transaction_id DESC")],
unique=False,
)
op.create_index(
"ix_asset_plant_plant_type_version_pk_validity",
"asset_plant_plant_type_version",
["uuid", "transaction_id", "end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_asset_plant_plant_type_version_transaction_id"),
"asset_plant_plant_type_version",
["transaction_id"],
unique=False,
)
# log_asset
op.create_table(
"log_asset",
sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.Column("log_uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.Column("asset_uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.ForeignKeyConstraint(
["asset_uuid"], ["asset.uuid"], name=op.f("fk_log_asset_asset_uuid_asset")
),
sa.ForeignKeyConstraint(
["log_uuid"], ["log.uuid"], name=op.f("fk_log_asset_log_uuid_log")
),
sa.PrimaryKeyConstraint("uuid", name=op.f("pk_log_asset")),
)
op.create_table(
"log_asset_version",
sa.Column(
"uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
),
sa.Column(
"log_uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=True
),
sa.Column(
"asset_uuid",
wuttjamaican.db.util.UUID(),
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_asset_version")
),
)
op.create_index(
op.f("ix_log_asset_version_end_transaction_id"),
"log_asset_version",
["end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_log_asset_version_operation_type"),
"log_asset_version",
["operation_type"],
unique=False,
)
op.create_index(
"ix_log_asset_version_pk_transaction_id",
"log_asset_version",
["uuid", sa.literal_column("transaction_id DESC")],
unique=False,
)
op.create_index(
"ix_log_asset_version_pk_validity",
"log_asset_version",
["uuid", "transaction_id", "end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_log_asset_version_transaction_id"),
"log_asset_version",
["transaction_id"],
unique=False,
)
# log_harvest
op.create_table(
"log_harvest",
sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.ForeignKeyConstraint(
["uuid"], ["log.uuid"], name=op.f("fk_log_harvest_uuid_log")
),
sa.PrimaryKeyConstraint("uuid", name=op.f("pk_log_harvest")),
)
op.create_table(
"log_harvest_version",
sa.Column(
"uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
),
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_harvest_version")
),
)
op.create_index(
op.f("ix_log_harvest_version_end_transaction_id"),
"log_harvest_version",
["end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_log_harvest_version_operation_type"),
"log_harvest_version",
["operation_type"],
unique=False,
)
op.create_index(
"ix_log_harvest_version_pk_transaction_id",
"log_harvest_version",
["uuid", sa.literal_column("transaction_id DESC")],
unique=False,
)
op.create_index(
"ix_log_harvest_version_pk_validity",
"log_harvest_version",
["uuid", "transaction_id", "end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_log_harvest_version_transaction_id"),
"log_harvest_version",
["transaction_id"],
unique=False,
)
# log_medical
op.create_table(
"log_medical",
sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.ForeignKeyConstraint(
["uuid"], ["log.uuid"], name=op.f("fk_log_medical_uuid_log")
),
sa.PrimaryKeyConstraint("uuid", name=op.f("pk_log_medical")),
)
op.create_table(
"log_medical_version",
sa.Column(
"uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
),
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_medical_version")
),
)
op.create_index(
op.f("ix_log_medical_version_end_transaction_id"),
"log_medical_version",
["end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_log_medical_version_operation_type"),
"log_medical_version",
["operation_type"],
unique=False,
)
op.create_index(
"ix_log_medical_version_pk_transaction_id",
"log_medical_version",
["uuid", sa.literal_column("transaction_id DESC")],
unique=False,
)
op.create_index(
"ix_log_medical_version_pk_validity",
"log_medical_version",
["uuid", "transaction_id", "end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_log_medical_version_transaction_id"),
"log_medical_version",
["transaction_id"],
unique=False,
)
# log_observation
op.create_table(
"log_observation",
sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.ForeignKeyConstraint(
["uuid"], ["log.uuid"], name=op.f("fk_log_observation_uuid_log")
),
sa.PrimaryKeyConstraint("uuid", name=op.f("pk_log_observation")),
)
op.create_table(
"log_observation_version",
sa.Column(
"uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
),
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_observation_version")
),
)
op.create_index(
op.f("ix_log_observation_version_end_transaction_id"),
"log_observation_version",
["end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_log_observation_version_operation_type"),
"log_observation_version",
["operation_type"],
unique=False,
)
op.create_index(
"ix_log_observation_version_pk_transaction_id",
"log_observation_version",
["uuid", sa.literal_column("transaction_id DESC")],
unique=False,
)
op.create_index(
"ix_log_observation_version_pk_validity",
"log_observation_version",
["uuid", "transaction_id", "end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_log_observation_version_transaction_id"),
"log_observation_version",
["transaction_id"],
unique=False,
)
def downgrade() -> None:
# log_observation
op.drop_index(
op.f("ix_log_observation_version_transaction_id"),
table_name="log_observation_version",
)
op.drop_index(
"ix_log_observation_version_pk_validity", table_name="log_observation_version"
)
op.drop_index(
"ix_log_observation_version_pk_transaction_id",
table_name="log_observation_version",
)
op.drop_index(
op.f("ix_log_observation_version_operation_type"),
table_name="log_observation_version",
)
op.drop_index(
op.f("ix_log_observation_version_end_transaction_id"),
table_name="log_observation_version",
)
op.drop_table("log_observation_version")
op.drop_table("log_observation")
# log_medical
op.drop_index(
op.f("ix_log_medical_version_transaction_id"), table_name="log_medical_version"
)
op.drop_index(
"ix_log_medical_version_pk_validity", table_name="log_medical_version"
)
op.drop_index(
"ix_log_medical_version_pk_transaction_id", table_name="log_medical_version"
)
op.drop_index(
op.f("ix_log_medical_version_operation_type"), table_name="log_medical_version"
)
op.drop_index(
op.f("ix_log_medical_version_end_transaction_id"),
table_name="log_medical_version",
)
op.drop_table("log_medical_version")
op.drop_table("log_medical")
# log_harvest
op.drop_index(
op.f("ix_log_harvest_version_transaction_id"), table_name="log_harvest_version"
)
op.drop_index(
"ix_log_harvest_version_pk_validity", table_name="log_harvest_version"
)
op.drop_index(
"ix_log_harvest_version_pk_transaction_id", table_name="log_harvest_version"
)
op.drop_index(
op.f("ix_log_harvest_version_operation_type"), table_name="log_harvest_version"
)
op.drop_index(
op.f("ix_log_harvest_version_end_transaction_id"),
table_name="log_harvest_version",
)
op.drop_table("log_harvest_version")
op.drop_table("log_harvest")
# log_asset
op.drop_index(
op.f("ix_log_asset_version_transaction_id"), table_name="log_asset_version"
)
op.drop_index("ix_log_asset_version_pk_validity", table_name="log_asset_version")
op.drop_index(
"ix_log_asset_version_pk_transaction_id", table_name="log_asset_version"
)
op.drop_index(
op.f("ix_log_asset_version_operation_type"), table_name="log_asset_version"
)
op.drop_index(
op.f("ix_log_asset_version_end_transaction_id"), table_name="log_asset_version"
)
op.drop_table("log_asset_version")
op.drop_table("log_asset")
# asset_plant_plant_type
op.drop_index(
op.f("ix_asset_plant_plant_type_version_transaction_id"),
table_name="asset_plant_plant_type_version",
)
op.drop_index(
"ix_asset_plant_plant_type_version_pk_validity",
table_name="asset_plant_plant_type_version",
)
op.drop_index(
"ix_asset_plant_plant_type_version_pk_transaction_id",
table_name="asset_plant_plant_type_version",
)
op.drop_index(
op.f("ix_asset_plant_plant_type_version_operation_type"),
table_name="asset_plant_plant_type_version",
)
op.drop_index(
op.f("ix_asset_plant_plant_type_version_end_transaction_id"),
table_name="asset_plant_plant_type_version",
)
op.drop_table("asset_plant_plant_type_version")
op.drop_table("asset_plant_plant_type")
# asset_plant
op.drop_index(
op.f("ix_asset_plant_version_transaction_id"), table_name="asset_plant_version"
)
op.drop_index(
"ix_asset_plant_version_pk_validity", table_name="asset_plant_version"
)
op.drop_index(
"ix_asset_plant_version_pk_transaction_id", table_name="asset_plant_version"
)
op.drop_index(
op.f("ix_asset_plant_version_operation_type"), table_name="asset_plant_version"
)
op.drop_index(
op.f("ix_asset_plant_version_end_transaction_id"),
table_name="asset_plant_version",
)
op.drop_table("asset_plant_version")
op.drop_table("asset_plant")
# plant_type
op.drop_index(
op.f("ix_plant_type_version_transaction_id"), table_name="plant_type_version"
)
op.drop_index("ix_plant_type_version_pk_validity", table_name="plant_type_version")
op.drop_index(
"ix_plant_type_version_pk_transaction_id", table_name="plant_type_version"
)
op.drop_index(
op.f("ix_plant_type_version_operation_type"), table_name="plant_type_version"
)
op.drop_index(
op.f("ix_plant_type_version_end_transaction_id"),
table_name="plant_type_version",
)
op.drop_table("plant_type_version")
op.drop_table("plant_type")

View file

@ -1,114 +0,0 @@
"""add Asset.owners
Revision ID: 12de43facb95
Revises: 85d4851e8292
Create Date: 2026-03-02 19:03:35.511398
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
import wuttjamaican.db.util
# revision identifiers, used by Alembic.
revision: str = "12de43facb95"
down_revision: Union[str, None] = "85d4851e8292"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# asset_owner
op.create_table(
"asset_owner",
sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.Column("asset_uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.Column("user_uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.ForeignKeyConstraint(
["asset_uuid"], ["asset.uuid"], name=op.f("fk_asset_owner_asset_uuid_asset")
),
sa.ForeignKeyConstraint(
["user_uuid"], ["user.uuid"], name=op.f("fk_asset_owner_user_uuid_user")
),
sa.PrimaryKeyConstraint("uuid", name=op.f("pk_asset_owner")),
)
op.create_table(
"asset_owner_version",
sa.Column(
"uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
),
sa.Column(
"asset_uuid",
wuttjamaican.db.util.UUID(),
autoincrement=False,
nullable=True,
),
sa.Column(
"user_uuid", wuttjamaican.db.util.UUID(), 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_owner_version")
),
)
op.create_index(
op.f("ix_asset_owner_version_end_transaction_id"),
"asset_owner_version",
["end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_asset_owner_version_operation_type"),
"asset_owner_version",
["operation_type"],
unique=False,
)
op.create_index(
"ix_asset_owner_version_pk_transaction_id",
"asset_owner_version",
["uuid", sa.literal_column("transaction_id DESC")],
unique=False,
)
op.create_index(
"ix_asset_owner_version_pk_validity",
"asset_owner_version",
["uuid", "transaction_id", "end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_asset_owner_version_transaction_id"),
"asset_owner_version",
["transaction_id"],
unique=False,
)
def downgrade() -> None:
# asset_owner
op.drop_index(
op.f("ix_asset_owner_version_transaction_id"), table_name="asset_owner_version"
)
op.drop_index(
"ix_asset_owner_version_pk_validity", table_name="asset_owner_version"
)
op.drop_index(
"ix_asset_owner_version_pk_transaction_id", table_name="asset_owner_version"
)
op.drop_index(
op.f("ix_asset_owner_version_operation_type"), table_name="asset_owner_version"
)
op.drop_index(
op.f("ix_asset_owner_version_end_transaction_id"),
table_name="asset_owner_version",
)
op.drop_table("asset_owner_version")
op.drop_table("asset_owner")

View file

@ -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")

View file

@ -1,119 +0,0 @@
"""add Quantity Types
Revision ID: 1f98d27cabeb
Revises: ea88e72a5fa5
Create Date: 2026-02-18 21:03:52.245619
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
import wuttjamaican.db.util
# revision identifiers, used by Alembic.
revision: str = "1f98d27cabeb"
down_revision: Union[str, None] = "ea88e72a5fa5"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# quantity_type
op.create_table(
"quantity_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_quantity_type")),
sa.UniqueConstraint("drupal_id", name=op.f("uq_quantity_type_drupal_id")),
sa.UniqueConstraint("farmos_uuid", name=op.f("uq_quantity_type_farmos_uuid")),
sa.UniqueConstraint("name", name=op.f("uq_quantity_type_name")),
)
op.create_table(
"quantity_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_quantity_type_version")
),
)
op.create_index(
op.f("ix_quantity_type_version_end_transaction_id"),
"quantity_type_version",
["end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_quantity_type_version_operation_type"),
"quantity_type_version",
["operation_type"],
unique=False,
)
op.create_index(
"ix_quantity_type_version_pk_transaction_id",
"quantity_type_version",
["uuid", sa.literal_column("transaction_id DESC")],
unique=False,
)
op.create_index(
"ix_quantity_type_version_pk_validity",
"quantity_type_version",
["uuid", "transaction_id", "end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_quantity_type_version_transaction_id"),
"quantity_type_version",
["transaction_id"],
unique=False,
)
def downgrade() -> None:
# quantity_type
op.drop_index(
op.f("ix_quantity_type_version_transaction_id"),
table_name="quantity_type_version",
)
op.drop_index(
"ix_quantity_type_version_pk_validity", table_name="quantity_type_version"
)
op.drop_index(
"ix_quantity_type_version_pk_transaction_id", table_name="quantity_type_version"
)
op.drop_index(
op.f("ix_quantity_type_version_operation_type"),
table_name="quantity_type_version",
)
op.drop_index(
op.f("ix_quantity_type_version_end_transaction_id"),
table_name="quantity_type_version",
)
op.drop_table("quantity_type_version")
op.drop_table("quantity_type")

View file

@ -1,41 +0,0 @@
"""add animal thumbnail url
Revision ID: 2a49127e974b
Revises: 8898184c5c75
Create Date: 2026-02-14 19:41:22.039343
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
import wuttjamaican.db.util
# revision identifiers, used by Alembic.
revision: str = "2a49127e974b"
down_revision: Union[str, None] = "8898184c5c75"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# animal
op.add_column(
"animal", sa.Column("thumbnail_url", sa.String(length=255), nullable=True)
)
op.add_column(
"animal_version",
sa.Column(
"thumbnail_url", sa.String(length=255), autoincrement=False, nullable=True
),
)
def downgrade() -> None:
# animal
op.drop_column("animal_version", "thumbnail_url")
op.drop_column("animal", "thumbnail_url")

View file

@ -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")

View file

@ -1,236 +0,0 @@
"""use shared base for Structure Assets
Revision ID: 34ec51d80f52
Revises: d882682c82f9
Create Date: 2026-02-15 13:19:18.814523
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
import wuttjamaican.db.util
# revision identifiers, used by Alembic.
revision: str = "34ec51d80f52"
down_revision: Union[str, None] = "d882682c82f9"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# asset_structure
op.create_table(
"asset_structure",
sa.Column("structure_type_uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.ForeignKeyConstraint(
["structure_type_uuid"],
["structure_type.uuid"],
name=op.f("fk_asset_structure_structure_type_uuid_structure_type"),
),
sa.ForeignKeyConstraint(
["uuid"], ["asset.uuid"], name=op.f("fk_asset_structure_uuid_asset")
),
sa.PrimaryKeyConstraint("uuid", name=op.f("pk_asset_structure")),
)
op.create_table(
"asset_structure_version",
sa.Column(
"structure_type_uuid",
wuttjamaican.db.util.UUID(),
autoincrement=False,
nullable=True,
),
sa.Column(
"uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
),
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_structure_version")
),
)
op.create_index(
op.f("ix_asset_structure_version_end_transaction_id"),
"asset_structure_version",
["end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_asset_structure_version_operation_type"),
"asset_structure_version",
["operation_type"],
unique=False,
)
op.create_index(
"ix_asset_structure_version_pk_transaction_id",
"asset_structure_version",
["uuid", sa.literal_column("transaction_id DESC")],
unique=False,
)
op.create_index(
"ix_asset_structure_version_pk_validity",
"asset_structure_version",
["uuid", "transaction_id", "end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_asset_structure_version_transaction_id"),
"asset_structure_version",
["transaction_id"],
unique=False,
)
# structure
op.drop_index(
op.f("ix_structure_version_end_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_pk_transaction_id"), table_name="structure_version"
)
op.drop_index(
op.f("ix_structure_version_pk_validity"), table_name="structure_version"
)
op.drop_index(
op.f("ix_structure_version_transaction_id"), table_name="structure_version"
)
op.drop_table("structure_version")
op.drop_table("structure")
def downgrade() -> None:
# structure
op.create_table(
"structure",
sa.Column("uuid", sa.UUID(), autoincrement=False, nullable=False),
sa.Column("name", sa.VARCHAR(length=100), autoincrement=False, nullable=False),
sa.Column("archived", sa.BOOLEAN(), autoincrement=False, nullable=False),
sa.Column(
"structure_type_uuid", sa.UUID(), autoincrement=False, nullable=False
),
sa.Column("is_location", sa.BOOLEAN(), autoincrement=False, nullable=False),
sa.Column("is_fixed", sa.BOOLEAN(), autoincrement=False, nullable=False),
sa.Column("notes", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column(
"image_url", sa.VARCHAR(length=255), autoincrement=False, nullable=True
),
sa.Column("farmos_uuid", sa.UUID(), autoincrement=False, nullable=True),
sa.Column("drupal_id", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column(
"thumbnail_url", sa.VARCHAR(length=255), autoincrement=False, 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"),
postgresql_include=[],
postgresql_nulls_not_distinct=False,
),
sa.UniqueConstraint(
"farmos_uuid",
name=op.f("uq_structure_farmos_uuid"),
postgresql_include=[],
postgresql_nulls_not_distinct=False,
),
sa.UniqueConstraint(
"name",
name=op.f("uq_structure_name"),
postgresql_include=[],
postgresql_nulls_not_distinct=False,
),
)
op.create_table(
"structure_version",
sa.Column("uuid", sa.UUID(), autoincrement=False, nullable=False),
sa.Column("name", sa.VARCHAR(length=100), autoincrement=False, nullable=True),
sa.Column("archived", sa.BOOLEAN(), autoincrement=False, nullable=True),
sa.Column("structure_type_uuid", sa.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.VARCHAR(length=255), autoincrement=False, nullable=True
),
sa.Column("farmos_uuid", sa.UUID(), autoincrement=False, nullable=True),
sa.Column("drupal_id", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column("transaction_id", sa.BIGINT(), autoincrement=False, nullable=False),
sa.Column(
"end_transaction_id", sa.BIGINT(), autoincrement=False, nullable=True
),
sa.Column("operation_type", sa.SMALLINT(), autoincrement=False, nullable=False),
sa.Column(
"thumbnail_url", sa.VARCHAR(length=255), autoincrement=False, nullable=True
),
sa.PrimaryKeyConstraint(
"uuid", "transaction_id", name=op.f("pk_structure_version")
),
)
op.create_index(
op.f("ix_structure_version_transaction_id"),
"structure_version",
["transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_structure_version_pk_validity"),
"structure_version",
["uuid", "transaction_id", "end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_structure_version_pk_transaction_id"),
"structure_version",
["uuid", sa.literal_column("transaction_id DESC")],
unique=False,
)
op.create_index(
op.f("ix_structure_version_operation_type"),
"structure_version",
["operation_type"],
unique=False,
)
op.create_index(
op.f("ix_structure_version_end_transaction_id"),
"structure_version",
["end_transaction_id"],
unique=False,
)
# asset_structure
op.drop_index(
op.f("ix_asset_structure_version_transaction_id"),
table_name="asset_structure_version",
)
op.drop_index(
"ix_asset_structure_version_pk_validity", table_name="asset_structure_version"
)
op.drop_index(
"ix_asset_structure_version_pk_transaction_id",
table_name="asset_structure_version",
)
op.drop_index(
op.f("ix_asset_structure_version_operation_type"),
table_name="asset_structure_version",
)
op.drop_index(
op.f("ix_asset_structure_version_end_transaction_id"),
table_name="asset_structure_version",
)
op.drop_table("asset_structure_version")
op.drop_table("asset_structure")

View file

@ -1,118 +0,0 @@
"""add LogLocation
Revision ID: 3bef7d380a38
Revises: f3c7e273bfa3
Create Date: 2026-02-28 20:41:56.051847
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
import wuttjamaican.db.util
# revision identifiers, used by Alembic.
revision: str = "3bef7d380a38"
down_revision: Union[str, None] = "f3c7e273bfa3"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# log_location
op.create_table(
"log_location",
sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.Column("log_uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.Column("asset_uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.ForeignKeyConstraint(
["asset_uuid"],
["asset.uuid"],
name=op.f("fk_log_location_asset_uuid_asset"),
),
sa.ForeignKeyConstraint(
["log_uuid"], ["log.uuid"], name=op.f("fk_log_location_log_uuid_log")
),
sa.PrimaryKeyConstraint("uuid", name=op.f("pk_log_location")),
)
op.create_table(
"log_location_version",
sa.Column(
"uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
),
sa.Column(
"log_uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=True
),
sa.Column(
"asset_uuid",
wuttjamaican.db.util.UUID(),
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_location_version")
),
)
op.create_index(
op.f("ix_log_location_version_end_transaction_id"),
"log_location_version",
["end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_log_location_version_operation_type"),
"log_location_version",
["operation_type"],
unique=False,
)
op.create_index(
"ix_log_location_version_pk_transaction_id",
"log_location_version",
["uuid", sa.literal_column("transaction_id DESC")],
unique=False,
)
op.create_index(
"ix_log_location_version_pk_validity",
"log_location_version",
["uuid", "transaction_id", "end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_log_location_version_transaction_id"),
"log_location_version",
["transaction_id"],
unique=False,
)
def downgrade() -> None:
# log_location
op.drop_index(
op.f("ix_log_location_version_transaction_id"),
table_name="log_location_version",
)
op.drop_index(
"ix_log_location_version_pk_validity", table_name="log_location_version"
)
op.drop_index(
"ix_log_location_version_pk_transaction_id", table_name="log_location_version"
)
op.drop_index(
op.f("ix_log_location_version_operation_type"),
table_name="log_location_version",
)
op.drop_index(
op.f("ix_log_location_version_end_transaction_id"),
table_name="log_location_version",
)
op.drop_table("log_location_version")
op.drop_table("log_location")

View file

@ -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")

View file

@ -1,37 +0,0 @@
"""remove unique for animal_type.name
Revision ID: 45c7718d2ed2
Revises: 5b6c87d8cddf
Create Date: 2026-02-27 16:53:59.310342
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
import wuttjamaican.db.util
# revision identifiers, used by Alembic.
revision: str = "45c7718d2ed2"
down_revision: Union[str, None] = "5b6c87d8cddf"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# animal_type
op.drop_constraint(op.f("uq_animal_type_name"), "animal_type", type_="unique")
def downgrade() -> None:
# animal_type
op.create_unique_constraint(
op.f("uq_animal_type_name"),
"animal_type",
["name"],
postgresql_nulls_not_distinct=False,
)

View file

@ -1,108 +0,0 @@
"""add LogOwner
Revision ID: 47d0ebd84554
Revises: 45c7718d2ed2
Create Date: 2026-02-28 19:18:49.122090
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
import wuttjamaican.db.util
# revision identifiers, used by Alembic.
revision: str = "47d0ebd84554"
down_revision: Union[str, None] = "45c7718d2ed2"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# log_owner
op.create_table(
"log_owner",
sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.Column("log_uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.Column("user_uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.ForeignKeyConstraint(
["log_uuid"], ["log.uuid"], name=op.f("fk_log_owner_log_uuid_log")
),
sa.ForeignKeyConstraint(
["user_uuid"], ["user.uuid"], name=op.f("fk_log_owner_user_uuid_user")
),
sa.PrimaryKeyConstraint("uuid", name=op.f("pk_log_owner")),
)
op.create_table(
"log_owner_version",
sa.Column(
"uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
),
sa.Column(
"log_uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=True
),
sa.Column(
"user_uuid", wuttjamaican.db.util.UUID(), 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_owner_version")
),
)
op.create_index(
op.f("ix_log_owner_version_end_transaction_id"),
"log_owner_version",
["end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_log_owner_version_operation_type"),
"log_owner_version",
["operation_type"],
unique=False,
)
op.create_index(
"ix_log_owner_version_pk_transaction_id",
"log_owner_version",
["uuid", sa.literal_column("transaction_id DESC")],
unique=False,
)
op.create_index(
"ix_log_owner_version_pk_validity",
"log_owner_version",
["uuid", "transaction_id", "end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_log_owner_version_transaction_id"),
"log_owner_version",
["transaction_id"],
unique=False,
)
def downgrade() -> None:
# log_owner
op.drop_index(
op.f("ix_log_owner_version_transaction_id"), table_name="log_owner_version"
)
op.drop_index("ix_log_owner_version_pk_validity", table_name="log_owner_version")
op.drop_index(
"ix_log_owner_version_pk_transaction_id", table_name="log_owner_version"
)
op.drop_index(
op.f("ix_log_owner_version_operation_type"), table_name="log_owner_version"
)
op.drop_index(
op.f("ix_log_owner_version_end_transaction_id"), table_name="log_owner_version"
)
op.drop_table("log_owner_version")
op.drop_table("log_owner")

View file

@ -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")

View file

@ -1,125 +0,0 @@
"""add LandAssetParent model
Revision ID: 554e6168c339
Revises: 8cc1565d38e7
Create Date: 2026-02-14 20:41:24.859064
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
import wuttjamaican.db.util
# revision identifiers, used by Alembic.
revision: str = "554e6168c339"
down_revision: Union[str, None] = "8cc1565d38e7"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# land_asset_parent
op.create_table(
"land_asset_parent",
sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.Column("land_asset_uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.Column("parent_asset_uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.ForeignKeyConstraint(
["land_asset_uuid"],
["land_asset.uuid"],
name=op.f("fk_land_asset_parent_land_asset_uuid_land_asset"),
),
sa.ForeignKeyConstraint(
["parent_asset_uuid"],
["land_asset.uuid"],
name=op.f("fk_land_asset_parent_parent_asset_uuid_land_asset"),
),
sa.PrimaryKeyConstraint("uuid", name=op.f("pk_land_asset_parent")),
)
op.create_table(
"land_asset_parent_version",
sa.Column(
"uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
),
sa.Column(
"land_asset_uuid",
wuttjamaican.db.util.UUID(),
autoincrement=False,
nullable=True,
),
sa.Column(
"parent_asset_uuid",
wuttjamaican.db.util.UUID(),
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_parent_version")
),
)
op.create_index(
op.f("ix_land_asset_parent_version_end_transaction_id"),
"land_asset_parent_version",
["end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_land_asset_parent_version_operation_type"),
"land_asset_parent_version",
["operation_type"],
unique=False,
)
op.create_index(
"ix_land_asset_parent_version_pk_transaction_id",
"land_asset_parent_version",
["uuid", sa.literal_column("transaction_id DESC")],
unique=False,
)
op.create_index(
"ix_land_asset_parent_version_pk_validity",
"land_asset_parent_version",
["uuid", "transaction_id", "end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_land_asset_parent_version_transaction_id"),
"land_asset_parent_version",
["transaction_id"],
unique=False,
)
def downgrade() -> None:
# land_asset_parent
op.drop_index(
op.f("ix_land_asset_parent_version_transaction_id"),
table_name="land_asset_parent_version",
)
op.drop_index(
"ix_land_asset_parent_version_pk_validity",
table_name="land_asset_parent_version",
)
op.drop_index(
"ix_land_asset_parent_version_pk_transaction_id",
table_name="land_asset_parent_version",
)
op.drop_index(
op.f("ix_land_asset_parent_version_operation_type"),
table_name="land_asset_parent_version",
)
op.drop_index(
op.f("ix_land_asset_parent_version_end_transaction_id"),
table_name="land_asset_parent_version",
)
op.drop_table("land_asset_parent_version")
op.drop_table("land_asset_parent")

View file

@ -1,293 +0,0 @@
"""add Standard Quantities
Revision ID: 5b6c87d8cddf
Revises: 1f98d27cabeb
Create Date: 2026-02-19 15:42:19.691148
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
import wuttjamaican.db.util
# revision identifiers, used by Alembic.
revision: str = "5b6c87d8cddf"
down_revision: Union[str, None] = "1f98d27cabeb"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# measure
op.create_table(
"measure",
sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.Column("name", sa.String(length=100), nullable=False),
sa.Column("drupal_id", sa.String(length=20), nullable=True),
sa.PrimaryKeyConstraint("uuid", name=op.f("pk_measure")),
sa.UniqueConstraint("drupal_id", name=op.f("uq_measure_drupal_id")),
sa.UniqueConstraint("name", name=op.f("uq_measure_name")),
)
op.create_table(
"measure_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(
"drupal_id", sa.String(length=20), 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_measure_version")
),
)
op.create_index(
op.f("ix_measure_version_end_transaction_id"),
"measure_version",
["end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_measure_version_operation_type"),
"measure_version",
["operation_type"],
unique=False,
)
op.create_index(
"ix_measure_version_pk_transaction_id",
"measure_version",
["uuid", sa.literal_column("transaction_id DESC")],
unique=False,
)
op.create_index(
"ix_measure_version_pk_validity",
"measure_version",
["uuid", "transaction_id", "end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_measure_version_transaction_id"),
"measure_version",
["transaction_id"],
unique=False,
)
# quantity
op.create_table(
"quantity",
sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.Column("quantity_type_id", sa.String(length=50), nullable=False),
sa.Column("measure_id", sa.String(length=20), nullable=False),
sa.Column("value_numerator", sa.Integer(), nullable=False),
sa.Column("value_denominator", sa.Integer(), nullable=False),
sa.Column("units_uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.Column("label", 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(
["measure_id"],
["measure.drupal_id"],
name=op.f("fk_quantity_measure_id_measure"),
),
sa.ForeignKeyConstraint(
["quantity_type_id"],
["quantity_type.drupal_id"],
name=op.f("fk_quantity_quantity_type_id_quantity_type"),
),
sa.ForeignKeyConstraint(
["units_uuid"], ["unit.uuid"], name=op.f("fk_quantity_units_uuid_unit")
),
sa.PrimaryKeyConstraint("uuid", name=op.f("pk_quantity")),
sa.UniqueConstraint("drupal_id", name=op.f("uq_quantity_drupal_id")),
sa.UniqueConstraint("farmos_uuid", name=op.f("uq_quantity_farmos_uuid")),
)
op.create_table(
"quantity_version",
sa.Column(
"uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
),
sa.Column(
"quantity_type_id", sa.String(length=50), autoincrement=False, nullable=True
),
sa.Column(
"measure_id", sa.String(length=20), autoincrement=False, nullable=True
),
sa.Column("value_numerator", sa.Integer(), autoincrement=False, nullable=True),
sa.Column(
"value_denominator", sa.Integer(), autoincrement=False, nullable=True
),
sa.Column(
"units_uuid",
wuttjamaican.db.util.UUID(),
autoincrement=False,
nullable=True,
),
sa.Column("label", 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_quantity_version")
),
)
op.create_index(
op.f("ix_quantity_version_end_transaction_id"),
"quantity_version",
["end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_quantity_version_operation_type"),
"quantity_version",
["operation_type"],
unique=False,
)
op.create_index(
"ix_quantity_version_pk_transaction_id",
"quantity_version",
["uuid", sa.literal_column("transaction_id DESC")],
unique=False,
)
op.create_index(
"ix_quantity_version_pk_validity",
"quantity_version",
["uuid", "transaction_id", "end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_quantity_version_transaction_id"),
"quantity_version",
["transaction_id"],
unique=False,
)
# quantity_standard
op.create_table(
"quantity_standard",
sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.ForeignKeyConstraint(
["uuid"], ["quantity.uuid"], name=op.f("fk_quantity_standard_uuid_quantity")
),
sa.PrimaryKeyConstraint("uuid", name=op.f("pk_quantity_standard")),
)
op.create_table(
"quantity_standard_version",
sa.Column(
"uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
),
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_quantity_standard_version")
),
)
op.create_index(
op.f("ix_quantity_standard_version_end_transaction_id"),
"quantity_standard_version",
["end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_quantity_standard_version_operation_type"),
"quantity_standard_version",
["operation_type"],
unique=False,
)
op.create_index(
"ix_quantity_standard_version_pk_transaction_id",
"quantity_standard_version",
["uuid", sa.literal_column("transaction_id DESC")],
unique=False,
)
op.create_index(
"ix_quantity_standard_version_pk_validity",
"quantity_standard_version",
["uuid", "transaction_id", "end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_quantity_standard_version_transaction_id"),
"quantity_standard_version",
["transaction_id"],
unique=False,
)
def downgrade() -> None:
# quantity_standard
op.drop_index(
op.f("ix_quantity_standard_version_transaction_id"),
table_name="quantity_standard_version",
)
op.drop_index(
"ix_quantity_standard_version_pk_validity",
table_name="quantity_standard_version",
)
op.drop_index(
"ix_quantity_standard_version_pk_transaction_id",
table_name="quantity_standard_version",
)
op.drop_index(
op.f("ix_quantity_standard_version_operation_type"),
table_name="quantity_standard_version",
)
op.drop_index(
op.f("ix_quantity_standard_version_end_transaction_id"),
table_name="quantity_standard_version",
)
op.drop_table("quantity_standard_version")
op.drop_table("quantity_standard")
# quantity
op.drop_index(
op.f("ix_quantity_version_transaction_id"), table_name="quantity_version"
)
op.drop_index("ix_quantity_version_pk_validity", table_name="quantity_version")
op.drop_index(
"ix_quantity_version_pk_transaction_id", table_name="quantity_version"
)
op.drop_index(
op.f("ix_quantity_version_operation_type"), table_name="quantity_version"
)
op.drop_index(
op.f("ix_quantity_version_end_transaction_id"), table_name="quantity_version"
)
op.drop_table("quantity_version")
op.drop_table("quantity")
# measure
op.drop_index(
op.f("ix_measure_version_transaction_id"), table_name="measure_version"
)
op.drop_index("ix_measure_version_pk_validity", table_name="measure_version")
op.drop_index("ix_measure_version_pk_transaction_id", table_name="measure_version")
op.drop_index(
op.f("ix_measure_version_operation_type"), table_name="measure_version"
)
op.drop_index(
op.f("ix_measure_version_end_transaction_id"), table_name="measure_version"
)
op.drop_table("measure_version")
op.drop_table("measure")

View file

@ -1,39 +0,0 @@
"""remove unwanted unique constraint
Revision ID: 5f474125a80e
Revises: 0771322957bd
Create Date: 2026-03-04 12:03:16.034291
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
import wuttjamaican.db.util
# revision identifiers, used by Alembic.
revision: str = "5f474125a80e"
down_revision: Union[str, None] = "0771322957bd"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# asset_land
op.drop_constraint(
op.f("uq_asset_land_land_type_uuid"), "asset_land", type_="unique"
)
def downgrade() -> None:
# asset_land
op.create_unique_constraint(
op.f("uq_asset_land_land_type_uuid"),
"asset_land",
["land_type_uuid"],
postgresql_nulls_not_distinct=False,
)

View file

@ -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")

View file

@ -1,111 +0,0 @@
"""add LogGroup
Revision ID: 74d32b4ec210
Revises: 3bef7d380a38
Create Date: 2026-02-28 21:35:24.125784
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
import wuttjamaican.db.util
# revision identifiers, used by Alembic.
revision: str = "74d32b4ec210"
down_revision: Union[str, None] = "3bef7d380a38"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# log_group
op.create_table(
"log_group",
sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.Column("log_uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.Column("asset_uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.ForeignKeyConstraint(
["asset_uuid"], ["asset.uuid"], name=op.f("fk_log_group_asset_uuid_asset")
),
sa.ForeignKeyConstraint(
["log_uuid"], ["log.uuid"], name=op.f("fk_log_group_log_uuid_log")
),
sa.PrimaryKeyConstraint("uuid", name=op.f("pk_log_group")),
)
op.create_table(
"log_group_version",
sa.Column(
"uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
),
sa.Column(
"log_uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=True
),
sa.Column(
"asset_uuid",
wuttjamaican.db.util.UUID(),
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_group_version")
),
)
op.create_index(
op.f("ix_log_group_version_end_transaction_id"),
"log_group_version",
["end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_log_group_version_operation_type"),
"log_group_version",
["operation_type"],
unique=False,
)
op.create_index(
"ix_log_group_version_pk_transaction_id",
"log_group_version",
["uuid", sa.literal_column("transaction_id DESC")],
unique=False,
)
op.create_index(
"ix_log_group_version_pk_validity",
"log_group_version",
["uuid", "transaction_id", "end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_log_group_version_transaction_id"),
"log_group_version",
["transaction_id"],
unique=False,
)
def downgrade() -> None:
# log_group
op.drop_index(
op.f("ix_log_group_version_transaction_id"), table_name="log_group_version"
)
op.drop_index("ix_log_group_version_pk_validity", table_name="log_group_version")
op.drop_index(
"ix_log_group_version_pk_transaction_id", table_name="log_group_version"
)
op.drop_index(
op.f("ix_log_group_version_operation_type"), table_name="log_group_version"
)
op.drop_index(
op.f("ix_log_group_version_end_transaction_id"), table_name="log_group_version"
)
op.drop_table("log_group_version")
op.drop_table("log_group")

View file

@ -1,52 +0,0 @@
"""add produces_eggs via EggMixin
Revision ID: 82a03f4ef1a4
Revises: 11e0e46f48a6
Create Date: 2026-02-18 18:45:36.015144
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
import wuttjamaican.db.util
# revision identifiers, used by Alembic.
revision: str = "82a03f4ef1a4"
down_revision: Union[str, None] = "11e0e46f48a6"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# asset_animal
op.add_column(
"asset_animal", sa.Column("produces_eggs", sa.Boolean(), nullable=True)
)
op.add_column(
"asset_animal_version",
sa.Column("produces_eggs", sa.Boolean(), autoincrement=False, nullable=True),
)
# asset_group
op.add_column(
"asset_group", sa.Column("produces_eggs", sa.Boolean(), nullable=True)
)
op.add_column(
"asset_group_version",
sa.Column("produces_eggs", sa.Boolean(), autoincrement=False, nullable=True),
)
def downgrade() -> None:
# asset_group
op.drop_column("asset_group_version", "produces_eggs")
op.drop_column("asset_group", "produces_eggs")
# asset_animal
op.drop_column("asset_animal_version", "produces_eggs")
op.drop_column("asset_animal", "produces_eggs")

View file

@ -1,37 +0,0 @@
"""add Log.quick
Revision ID: 85d4851e8292
Revises: d459db991404
Create Date: 2026-03-02 18:42:56.070281
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
import wuttjamaican.db.util
# revision identifiers, used by Alembic.
revision: str = "85d4851e8292"
down_revision: Union[str, None] = "d459db991404"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# log
op.add_column("log", sa.Column("quick", sa.String(length=20), nullable=True))
op.add_column(
"log_version",
sa.Column("quick", sa.String(length=20), autoincrement=False, nullable=True),
)
def downgrade() -> None:
# log
op.drop_column("log_version", "quick")
op.drop_column("log", "quick")

View file

@ -1,250 +0,0 @@
"""convert active to archived
Revision ID: 8898184c5c75
Revises: 3e2ef02bf264
Create Date: 2026-02-14 18:41:23.042951
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
import wuttjamaican.db.util
# revision identifiers, used by Alembic.
revision: str = "8898184c5c75"
down_revision: Union[str, None] = "3e2ef02bf264"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# animal
op.alter_column("animal", "active", new_column_name="archived")
animal = sa.sql.table(
"animal",
sa.sql.column("uuid"),
sa.sql.column("archived"),
)
cursor = op.get_bind().execute(animal.select())
for row in cursor.fetchall():
op.get_bind().execute(
animal.update()
.where(animal.c.uuid == row.uuid)
.values({"archived": not row.archived})
)
op.alter_column("animal_version", "active", new_column_name="archived")
animal_version = sa.sql.table(
"animal_version",
sa.sql.column("uuid"),
sa.sql.column("archived"),
)
cursor = op.get_bind().execute(animal_version.select())
for row in cursor.fetchall():
op.get_bind().execute(
animal_version.update()
.where(animal_version.c.uuid == row.uuid)
.values({"archived": not row.archived})
)
# group
op.alter_column("group", "active", new_column_name="archived")
group = sa.sql.table(
"group",
sa.sql.column("uuid"),
sa.sql.column("archived"),
)
cursor = op.get_bind().execute(group.select())
for row in cursor.fetchall():
op.get_bind().execute(
group.update()
.where(group.c.uuid == row.uuid)
.values({"archived": not row.archived})
)
op.alter_column("group_version", "active", new_column_name="archived")
group_version = sa.sql.table(
"group_version",
sa.sql.column("uuid"),
sa.sql.column("archived"),
)
cursor = op.get_bind().execute(group_version.select())
for row in cursor.fetchall():
op.get_bind().execute(
group_version.update()
.where(group_version.c.uuid == row.uuid)
.values({"archived": not row.archived})
)
# land_asset
op.alter_column("land_asset", "active", new_column_name="archived")
land_asset = sa.sql.table(
"land_asset",
sa.sql.column("uuid"),
sa.sql.column("archived"),
)
cursor = op.get_bind().execute(land_asset.select())
for row in cursor.fetchall():
op.get_bind().execute(
land_asset.update()
.where(land_asset.c.uuid == row.uuid)
.values({"archived": not row.archived})
)
op.alter_column("land_asset_version", "active", new_column_name="archived")
land_asset_version = sa.sql.table(
"land_asset_version",
sa.sql.column("uuid"),
sa.sql.column("archived"),
)
cursor = op.get_bind().execute(land_asset_version.select())
for row in cursor.fetchall():
op.get_bind().execute(
land_asset_version.update()
.where(land_asset_version.c.uuid == row.uuid)
.values({"archived": not row.archived})
)
# structure
op.alter_column("structure", "active", new_column_name="archived")
structure = sa.sql.table(
"structure",
sa.sql.column("uuid"),
sa.sql.column("archived"),
)
cursor = op.get_bind().execute(structure.select())
for row in cursor.fetchall():
op.get_bind().execute(
structure.update()
.where(structure.c.uuid == row.uuid)
.values({"archived": not row.archived})
)
op.alter_column("structure_version", "active", new_column_name="archived")
structure_version = sa.sql.table(
"structure_version",
sa.sql.column("uuid"),
sa.sql.column("archived"),
)
cursor = op.get_bind().execute(structure_version.select())
for row in cursor.fetchall():
op.get_bind().execute(
structure_version.update()
.where(structure_version.c.uuid == row.uuid)
.values({"archived": not row.archived})
)
def downgrade() -> None:
# structure
op.alter_column("structure", "archived", new_column_name="active")
structure = sa.sql.table(
"structure",
sa.sql.column("uuid"),
sa.sql.column("active"),
)
cursor = op.get_bind().execute(structure.select())
for row in cursor.fetchall():
op.get_bind().execute(
structure.update()
.where(structure.c.uuid == row.uuid)
.values({"active": not row.active})
)
op.alter_column("structure_version", "archived", new_column_name="active")
structure_version = sa.sql.table(
"structure_version",
sa.sql.column("uuid"),
sa.sql.column("active"),
)
cursor = op.get_bind().execute(structure_version.select())
for row in cursor.fetchall():
op.get_bind().execute(
structure_version.update()
.where(structure_version.c.uuid == row.uuid)
.values({"active": not row.active})
)
# land_asset
op.alter_column("land_asset", "archived", new_column_name="active")
land_asset = sa.sql.table(
"land_asset",
sa.sql.column("uuid"),
sa.sql.column("active"),
)
cursor = op.get_bind().execute(land_asset.select())
for row in cursor.fetchall():
op.get_bind().execute(
land_asset.update()
.where(land_asset.c.uuid == row.uuid)
.values({"active": not row.active})
)
op.alter_column("land_asset_version", "archived", new_column_name="active")
land_asset_version = sa.sql.table(
"land_asset_version",
sa.sql.column("uuid"),
sa.sql.column("active"),
)
cursor = op.get_bind().execute(land_asset_version.select())
for row in cursor.fetchall():
op.get_bind().execute(
land_asset_version.update()
.where(land_asset_version.c.uuid == row.uuid)
.values({"active": not row.active})
)
# group
op.alter_column("group", "archived", new_column_name="active")
group = sa.sql.table(
"group",
sa.sql.column("uuid"),
sa.sql.column("active"),
)
cursor = op.get_bind().execute(group.select())
for row in cursor.fetchall():
op.get_bind().execute(
group.update()
.where(group.c.uuid == row.uuid)
.values({"active": not row.active})
)
op.alter_column("group_version", "archived", new_column_name="active")
group_version = sa.sql.table(
"group_version",
sa.sql.column("uuid"),
sa.sql.column("active"),
)
cursor = op.get_bind().execute(group_version.select())
for row in cursor.fetchall():
op.get_bind().execute(
group_version.update()
.where(group_version.c.uuid == row.uuid)
.values({"active": not row.active})
)
# animal
op.alter_column("animal", "archived", new_column_name="active")
animal = sa.sql.table(
"animal",
sa.sql.column("uuid"),
sa.sql.column("active"),
)
cursor = op.get_bind().execute(animal.select())
for row in cursor.fetchall():
op.get_bind().execute(
animal.update()
.where(animal.c.uuid == row.uuid)
.values({"active": not row.active})
)
op.alter_column("animal_version", "archived", new_column_name="active")
animal_version = sa.sql.table(
"animal_version",
sa.sql.column("uuid"),
sa.sql.column("active"),
)
cursor = op.get_bind().execute(animal_version.select())
for row in cursor.fetchall():
op.get_bind().execute(
animal_version.update()
.where(animal_version.c.uuid == row.uuid)
.values({"active": not row.active})
)

View file

@ -1,41 +0,0 @@
"""add structure thumbnail url
Revision ID: 8cc1565d38e7
Revises: 2a49127e974b
Create Date: 2026-02-14 20:07:33.913573
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
import wuttjamaican.db.util
# revision identifiers, used by Alembic.
revision: str = "8cc1565d38e7"
down_revision: Union[str, None] = "2a49127e974b"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# structure
op.add_column(
"structure", sa.Column("thumbnail_url", sa.String(length=255), nullable=True)
)
op.add_column(
"structure_version",
sa.Column(
"thumbnail_url", sa.String(length=255), autoincrement=False, nullable=True
),
)
def downgrade() -> None:
# structure
op.drop_column("structure_version", "thumbnail_url")
op.drop_column("structure", "thumbnail_url")

View file

@ -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")

View file

@ -1,118 +0,0 @@
"""add LogQuantity
Revision ID: 9e875e5cbdc1
Revises: 74d32b4ec210
Create Date: 2026-02-28 21:55:31.876087
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
import wuttjamaican.db.util
# revision identifiers, used by Alembic.
revision: str = "9e875e5cbdc1"
down_revision: Union[str, None] = "74d32b4ec210"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# log_quantity
op.create_table(
"log_quantity",
sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.Column("log_uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.Column("quantity_uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.ForeignKeyConstraint(
["log_uuid"], ["log.uuid"], name=op.f("fk_log_quantity_log_uuid_log")
),
sa.ForeignKeyConstraint(
["quantity_uuid"],
["quantity.uuid"],
name=op.f("fk_log_quantity_quantity_uuid_quantity"),
),
sa.PrimaryKeyConstraint("uuid", name=op.f("pk_log_quantity")),
)
op.create_table(
"log_quantity_version",
sa.Column(
"uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
),
sa.Column(
"log_uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=True
),
sa.Column(
"quantity_uuid",
wuttjamaican.db.util.UUID(),
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_quantity_version")
),
)
op.create_index(
op.f("ix_log_quantity_version_end_transaction_id"),
"log_quantity_version",
["end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_log_quantity_version_operation_type"),
"log_quantity_version",
["operation_type"],
unique=False,
)
op.create_index(
"ix_log_quantity_version_pk_transaction_id",
"log_quantity_version",
["uuid", sa.literal_column("transaction_id DESC")],
unique=False,
)
op.create_index(
"ix_log_quantity_version_pk_validity",
"log_quantity_version",
["uuid", "transaction_id", "end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_log_quantity_version_transaction_id"),
"log_quantity_version",
["transaction_id"],
unique=False,
)
def downgrade() -> None:
# log_quantity
op.drop_index(
op.f("ix_log_quantity_version_transaction_id"),
table_name="log_quantity_version",
)
op.drop_index(
"ix_log_quantity_version_pk_validity", table_name="log_quantity_version"
)
op.drop_index(
"ix_log_quantity_version_pk_transaction_id", table_name="log_quantity_version"
)
op.drop_index(
op.f("ix_log_quantity_version_operation_type"),
table_name="log_quantity_version",
)
op.drop_index(
op.f("ix_log_quantity_version_end_transaction_id"),
table_name="log_quantity_version",
)
op.drop_table("log_quantity_version")
op.drop_table("log_quantity")

View file

@ -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")

View file

@ -1,194 +0,0 @@
"""use shared base for Group Assets
Revision ID: aecfd9175624
Revises: 34ec51d80f52
Create Date: 2026-02-15 13:57:01.055304
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
import wuttjamaican.db.util
# revision identifiers, used by Alembic.
revision: str = "aecfd9175624"
down_revision: Union[str, None] = "34ec51d80f52"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# asset_group
op.create_table(
"asset_group",
sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.ForeignKeyConstraint(
["uuid"], ["asset.uuid"], name=op.f("fk_asset_group_uuid_asset")
),
sa.PrimaryKeyConstraint("uuid", name=op.f("pk_asset_group")),
)
op.create_table(
"asset_group_version",
sa.Column(
"uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
),
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_group_version")
),
)
op.create_index(
op.f("ix_asset_group_version_end_transaction_id"),
"asset_group_version",
["end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_asset_group_version_operation_type"),
"asset_group_version",
["operation_type"],
unique=False,
)
op.create_index(
"ix_asset_group_version_pk_transaction_id",
"asset_group_version",
["uuid", sa.literal_column("transaction_id DESC")],
unique=False,
)
op.create_index(
"ix_asset_group_version_pk_validity",
"asset_group_version",
["uuid", "transaction_id", "end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_asset_group_version_transaction_id"),
"asset_group_version",
["transaction_id"],
unique=False,
)
# group
op.drop_index(
op.f("ix_group_version_end_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_pk_transaction_id"), table_name="group_version"
)
op.drop_index(op.f("ix_group_version_pk_validity"), table_name="group_version")
op.drop_index(op.f("ix_group_version_transaction_id"), table_name="group_version")
op.drop_table("group_version")
op.drop_table("group")
def downgrade() -> None:
# group
op.create_table(
"group",
sa.Column("uuid", sa.UUID(), autoincrement=False, nullable=False),
sa.Column("name", sa.VARCHAR(length=100), autoincrement=False, nullable=False),
sa.Column("is_location", sa.BOOLEAN(), autoincrement=False, nullable=False),
sa.Column("is_fixed", sa.BOOLEAN(), autoincrement=False, nullable=False),
sa.Column("archived", sa.BOOLEAN(), autoincrement=False, nullable=False),
sa.Column("notes", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column("farmos_uuid", sa.UUID(), autoincrement=False, nullable=True),
sa.Column("drupal_id", sa.INTEGER(), autoincrement=False, nullable=True),
sa.PrimaryKeyConstraint("uuid", name=op.f("pk_group")),
sa.UniqueConstraint(
"drupal_id",
name=op.f("uq_group_drupal_id"),
postgresql_include=[],
postgresql_nulls_not_distinct=False,
),
sa.UniqueConstraint(
"farmos_uuid",
name=op.f("uq_group_farmos_uuid"),
postgresql_include=[],
postgresql_nulls_not_distinct=False,
),
sa.UniqueConstraint(
"name",
name=op.f("uq_group_name"),
postgresql_include=[],
postgresql_nulls_not_distinct=False,
),
)
op.create_table(
"group_version",
sa.Column("uuid", sa.UUID(), autoincrement=False, nullable=False),
sa.Column("name", sa.VARCHAR(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("archived", sa.BOOLEAN(), autoincrement=False, nullable=True),
sa.Column("notes", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column("farmos_uuid", sa.UUID(), autoincrement=False, nullable=True),
sa.Column("drupal_id", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column("transaction_id", sa.BIGINT(), autoincrement=False, nullable=False),
sa.Column(
"end_transaction_id", sa.BIGINT(), autoincrement=False, nullable=True
),
sa.Column("operation_type", sa.SMALLINT(), autoincrement=False, nullable=False),
sa.PrimaryKeyConstraint(
"uuid", "transaction_id", name=op.f("pk_group_version")
),
)
op.create_index(
op.f("ix_group_version_transaction_id"),
"group_version",
["transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_group_version_pk_validity"),
"group_version",
["uuid", "transaction_id", "end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_group_version_pk_transaction_id"),
"group_version",
["uuid", sa.literal_column("transaction_id DESC")],
unique=False,
)
op.create_index(
op.f("ix_group_version_operation_type"),
"group_version",
["operation_type"],
unique=False,
)
op.create_index(
op.f("ix_group_version_end_transaction_id"),
"group_version",
["end_transaction_id"],
unique=False,
)
# asset_group
op.drop_index(
op.f("ix_asset_group_version_transaction_id"), table_name="asset_group_version"
)
op.drop_index(
"ix_asset_group_version_pk_validity", table_name="asset_group_version"
)
op.drop_index(
"ix_asset_group_version_pk_transaction_id", table_name="asset_group_version"
)
op.drop_index(
op.f("ix_asset_group_version_operation_type"), table_name="asset_group_version"
)
op.drop_index(
op.f("ix_asset_group_version_end_transaction_id"),
table_name="asset_group_version",
)
op.drop_table("asset_group_version")
op.drop_table("asset_group")

View file

@ -1,37 +0,0 @@
"""remove AnimalType.changed
Revision ID: b8cd4a8f981f
Revises: aecfd9175624
Create Date: 2026-02-17 18:11:06.110003
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
import wuttjamaican.db.util
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
revision: str = "b8cd4a8f981f"
down_revision: Union[str, None] = "aecfd9175624"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# animal_type
op.drop_column("animal_type", "changed")
def downgrade() -> None:
# animal_type
op.add_column(
"animal_type",
sa.Column(
"changed", postgresql.TIMESTAMP(), autoincrement=False, nullable=True
),
)

View file

@ -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")

View file

@ -1,37 +0,0 @@
"""add MedicalLog.vet
Revision ID: d459db991404
Revises: 9e875e5cbdc1
Create Date: 2026-02-28 22:17:57.001134
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
import wuttjamaican.db.util
# revision identifiers, used by Alembic.
revision: str = "d459db991404"
down_revision: Union[str, None] = "9e875e5cbdc1"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# log_medical
op.add_column("log_medical", sa.Column("vet", sa.String(length=100), nullable=True))
op.add_column(
"log_medical_version",
sa.Column("vet", sa.String(length=100), autoincrement=False, nullable=True),
)
def downgrade() -> None:
# log_medical
op.drop_column("log_medical_version", "vet")
op.drop_column("log_medical", "vet")

View file

@ -1,333 +0,0 @@
"""add generic, animal assets
Revision ID: d6e8d16d6854
Revises: 554e6168c339
Create Date: 2026-02-15 09:11:04.886362
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
import wuttjamaican.db.util
# revision identifiers, used by Alembic.
revision: str = "d6e8d16d6854"
down_revision: Union[str, None] = "554e6168c339"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# animal
op.drop_table("animal")
op.drop_index(
op.f("ix_animal_version_end_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_pk_transaction_id"), table_name="animal_version"
)
op.drop_index(op.f("ix_animal_version_pk_validity"), table_name="animal_version")
op.drop_index(op.f("ix_animal_version_transaction_id"), table_name="animal_version")
op.drop_table("animal_version")
# asset
op.create_table(
"asset",
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.Column("asset_type", sa.String(length=100), nullable=False),
sa.Column("asset_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("notes", sa.Text(), nullable=True),
sa.Column("thumbnail_url", sa.String(length=255), nullable=True),
sa.Column("image_url", sa.String(length=255), nullable=True),
sa.Column("archived", sa.Boolean(), nullable=False),
sa.ForeignKeyConstraint(
["asset_type"],
["asset_type.drupal_id"],
name=op.f("fk_asset_asset_type_asset_type"),
),
sa.PrimaryKeyConstraint("uuid", name=op.f("pk_asset")),
sa.UniqueConstraint("drupal_id", name=op.f("uq_asset_drupal_id")),
sa.UniqueConstraint("farmos_uuid", name=op.f("uq_asset_farmos_uuid")),
)
op.create_table(
"asset_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(
"asset_type", sa.String(length=100), autoincrement=False, nullable=True
),
sa.Column(
"asset_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("notes", sa.Text(), autoincrement=False, nullable=True),
sa.Column(
"thumbnail_url", sa.String(length=255), autoincrement=False, nullable=True
),
sa.Column(
"image_url", sa.String(length=255), autoincrement=False, nullable=True
),
sa.Column("archived", sa.Boolean(), 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_version")
),
)
op.create_index(
op.f("ix_asset_version_end_transaction_id"),
"asset_version",
["end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_asset_version_operation_type"),
"asset_version",
["operation_type"],
unique=False,
)
op.create_index(
"ix_asset_version_pk_transaction_id",
"asset_version",
["uuid", sa.literal_column("transaction_id DESC")],
unique=False,
)
op.create_index(
"ix_asset_version_pk_validity",
"asset_version",
["uuid", "transaction_id", "end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_asset_version_transaction_id"),
"asset_version",
["transaction_id"],
unique=False,
)
# asset_animal
op.create_table(
"asset_animal",
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("uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.ForeignKeyConstraint(
["animal_type_uuid"],
["animal_type.uuid"],
name=op.f("fk_asset_animal_animal_type_uuid_animal_type"),
),
sa.ForeignKeyConstraint(
["uuid"], ["asset.uuid"], name=op.f("fk_asset_animal_uuid_asset")
),
sa.PrimaryKeyConstraint("uuid", name=op.f("pk_asset_animal")),
)
op.create_table(
"asset_animal_version",
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(
"uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
),
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_animal_version")
),
)
op.create_index(
op.f("ix_asset_animal_version_end_transaction_id"),
"asset_animal_version",
["end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_asset_animal_version_operation_type"),
"asset_animal_version",
["operation_type"],
unique=False,
)
op.create_index(
"ix_asset_animal_version_pk_transaction_id",
"asset_animal_version",
["uuid", sa.literal_column("transaction_id DESC")],
unique=False,
)
op.create_index(
"ix_asset_animal_version_pk_validity",
"asset_animal_version",
["uuid", "transaction_id", "end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_asset_animal_version_transaction_id"),
"asset_animal_version",
["transaction_id"],
unique=False,
)
def downgrade() -> None:
# asset_animal
op.drop_index(
op.f("ix_asset_animal_version_transaction_id"),
table_name="asset_animal_version",
)
op.drop_index(
"ix_asset_animal_version_pk_validity", table_name="asset_animal_version"
)
op.drop_index(
"ix_asset_animal_version_pk_transaction_id", table_name="asset_animal_version"
)
op.drop_index(
op.f("ix_asset_animal_version_operation_type"),
table_name="asset_animal_version",
)
op.drop_index(
op.f("ix_asset_animal_version_end_transaction_id"),
table_name="asset_animal_version",
)
op.drop_table("asset_animal_version")
op.drop_table("asset_animal")
# asset
op.drop_index(op.f("ix_asset_version_transaction_id"), table_name="asset_version")
op.drop_index("ix_asset_version_pk_validity", table_name="asset_version")
op.drop_index("ix_asset_version_pk_transaction_id", table_name="asset_version")
op.drop_index(op.f("ix_asset_version_operation_type"), table_name="asset_version")
op.drop_index(
op.f("ix_asset_version_end_transaction_id"), table_name="asset_version"
)
op.drop_table("asset_version")
op.drop_table("asset")
# animal
op.create_table(
"animal",
sa.Column("uuid", sa.UUID(), autoincrement=False, nullable=False),
sa.Column("name", sa.VARCHAR(length=100), autoincrement=False, nullable=False),
sa.Column("animal_type_uuid", sa.UUID(), autoincrement=False, nullable=False),
sa.Column("birthdate", sa.DateTime(), autoincrement=False, nullable=True),
sa.Column("sex", sa.VARCHAR(length=1), autoincrement=False, nullable=True),
sa.Column("is_sterile", sa.BOOLEAN(), autoincrement=False, nullable=True),
sa.Column("archived", sa.BOOLEAN(), autoincrement=False, nullable=False),
sa.Column("notes", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column(
"image_url", sa.VARCHAR(length=255), autoincrement=False, nullable=True
),
sa.Column("farmos_uuid", sa.UUID(), autoincrement=False, nullable=True),
sa.Column("drupal_id", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column(
"thumbnail_url", sa.VARCHAR(length=255), autoincrement=False, 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"),
postgresql_include=[],
postgresql_nulls_not_distinct=False,
),
sa.UniqueConstraint(
"farmos_uuid",
name=op.f("uq_animal_farmos_uuid"),
postgresql_include=[],
postgresql_nulls_not_distinct=False,
),
)
op.create_table(
"animal_version",
sa.Column("uuid", sa.UUID(), autoincrement=False, nullable=False),
sa.Column("name", sa.VARCHAR(length=100), autoincrement=False, nullable=True),
sa.Column("animal_type_uuid", sa.UUID(), autoincrement=False, nullable=True),
sa.Column(
"birthdate", postgresql.TIMESTAMP(), autoincrement=False, nullable=True
),
sa.Column("sex", sa.VARCHAR(length=1), autoincrement=False, nullable=True),
sa.Column("is_sterile", sa.BOOLEAN(), autoincrement=False, nullable=True),
sa.Column("archived", sa.BOOLEAN(), autoincrement=False, nullable=True),
sa.Column("notes", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column(
"image_url", sa.VARCHAR(length=255), autoincrement=False, nullable=True
),
sa.Column("farmos_uuid", sa.UUID(), autoincrement=False, nullable=True),
sa.Column("drupal_id", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column("transaction_id", sa.BIGINT(), autoincrement=False, nullable=False),
sa.Column(
"end_transaction_id", sa.BIGINT(), autoincrement=False, nullable=True
),
sa.Column("operation_type", sa.SMALLINT(), autoincrement=False, nullable=False),
sa.Column(
"thumbnail_url", sa.VARCHAR(length=255), autoincrement=False, nullable=True
),
sa.PrimaryKeyConstraint(
"uuid", "transaction_id", name=op.f("pk_animal_version")
),
)
op.create_index(
op.f("ix_animal_version_transaction_id"),
"animal_version",
["transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_animal_version_pk_validity"),
"animal_version",
["uuid", "transaction_id", "end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_animal_version_pk_transaction_id"),
"animal_version",
["uuid", sa.literal_column("transaction_id DESC")],
unique=False,
)
op.create_index(
op.f("ix_animal_version_operation_type"),
"animal_version",
["operation_type"],
unique=False,
)
op.create_index(
op.f("ix_animal_version_end_transaction_id"),
"animal_version",
["end_transaction_id"],
unique=False,
)

View file

@ -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")

View file

@ -1,411 +0,0 @@
"""use shared base for Land Assets
Revision ID: d882682c82f9
Revises: d6e8d16d6854
Create Date: 2026-02-15 12:00:27.036011
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
import wuttjamaican.db.util
# revision identifiers, used by Alembic.
revision: str = "d882682c82f9"
down_revision: Union[str, None] = "d6e8d16d6854"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# asset_parent
op.create_table(
"asset_parent",
sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.Column("asset_uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.Column("parent_uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.ForeignKeyConstraint(
["asset_uuid"],
["asset.uuid"],
name=op.f("fk_asset_parent_asset_uuid_asset"),
),
sa.ForeignKeyConstraint(
["parent_uuid"],
["asset.uuid"],
name=op.f("fk_asset_parent_parent_uuid_asset"),
),
sa.PrimaryKeyConstraint("uuid", name=op.f("pk_asset_parent")),
)
op.create_table(
"asset_parent_version",
sa.Column(
"uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
),
sa.Column(
"asset_uuid",
wuttjamaican.db.util.UUID(),
autoincrement=False,
nullable=True,
),
sa.Column(
"parent_uuid",
wuttjamaican.db.util.UUID(),
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_parent_version")
),
)
op.create_index(
op.f("ix_asset_parent_version_end_transaction_id"),
"asset_parent_version",
["end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_asset_parent_version_operation_type"),
"asset_parent_version",
["operation_type"],
unique=False,
)
op.create_index(
"ix_asset_parent_version_pk_transaction_id",
"asset_parent_version",
["uuid", sa.literal_column("transaction_id DESC")],
unique=False,
)
op.create_index(
"ix_asset_parent_version_pk_validity",
"asset_parent_version",
["uuid", "transaction_id", "end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_asset_parent_version_transaction_id"),
"asset_parent_version",
["transaction_id"],
unique=False,
)
# asset_land
op.create_table(
"asset_land",
sa.Column("land_type_uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.ForeignKeyConstraint(
["land_type_uuid"],
["land_type.uuid"],
name=op.f("fk_asset_land_land_type_uuid_land_type"),
),
sa.ForeignKeyConstraint(
["uuid"], ["asset.uuid"], name=op.f("fk_asset_land_uuid_asset")
),
sa.PrimaryKeyConstraint("uuid", name=op.f("pk_asset_land")),
sa.UniqueConstraint(
"land_type_uuid", name=op.f("uq_asset_land_land_type_uuid")
),
)
op.create_table(
"asset_land_version",
sa.Column(
"land_type_uuid",
wuttjamaican.db.util.UUID(),
autoincrement=False,
nullable=True,
),
sa.Column(
"uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
),
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_land_version")
),
)
op.create_index(
op.f("ix_asset_land_version_end_transaction_id"),
"asset_land_version",
["end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_asset_land_version_operation_type"),
"asset_land_version",
["operation_type"],
unique=False,
)
op.create_index(
"ix_asset_land_version_pk_transaction_id",
"asset_land_version",
["uuid", sa.literal_column("transaction_id DESC")],
unique=False,
)
op.create_index(
"ix_asset_land_version_pk_validity",
"asset_land_version",
["uuid", "transaction_id", "end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_asset_land_version_transaction_id"),
"asset_land_version",
["transaction_id"],
unique=False,
)
# land_asset_parent
op.drop_index(
op.f("ix_land_asset_parent_version_end_transaction_id"),
table_name="land_asset_parent_version",
)
op.drop_index(
op.f("ix_land_asset_parent_version_operation_type"),
table_name="land_asset_parent_version",
)
op.drop_index(
op.f("ix_land_asset_parent_version_pk_transaction_id"),
table_name="land_asset_parent_version",
)
op.drop_index(
op.f("ix_land_asset_parent_version_pk_validity"),
table_name="land_asset_parent_version",
)
op.drop_index(
op.f("ix_land_asset_parent_version_transaction_id"),
table_name="land_asset_parent_version",
)
op.drop_table("land_asset_parent_version")
op.drop_table("land_asset_parent")
# land_asset
op.drop_index(
op.f("ix_land_asset_version_end_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_pk_transaction_id"), table_name="land_asset_version"
)
op.drop_index(
op.f("ix_land_asset_version_pk_validity"), table_name="land_asset_version"
)
op.drop_index(
op.f("ix_land_asset_version_transaction_id"), table_name="land_asset_version"
)
op.drop_table("land_asset_version")
op.drop_table("land_asset")
def downgrade() -> None:
# land_asset
op.create_table(
"land_asset",
sa.Column("uuid", sa.UUID(), autoincrement=False, nullable=False),
sa.Column("name", sa.VARCHAR(length=100), autoincrement=False, nullable=False),
sa.Column("land_type_uuid", sa.UUID(), autoincrement=False, nullable=False),
sa.Column("is_location", sa.BOOLEAN(), autoincrement=False, nullable=False),
sa.Column("is_fixed", sa.BOOLEAN(), autoincrement=False, nullable=False),
sa.Column("notes", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column("archived", sa.BOOLEAN(), autoincrement=False, nullable=False),
sa.Column("farmos_uuid", sa.UUID(), autoincrement=False, nullable=True),
sa.Column("drupal_id", sa.INTEGER(), autoincrement=False, 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"),
postgresql_include=[],
postgresql_nulls_not_distinct=False,
),
sa.UniqueConstraint(
"farmos_uuid",
name=op.f("uq_land_asset_farmos_uuid"),
postgresql_include=[],
postgresql_nulls_not_distinct=False,
),
sa.UniqueConstraint(
"land_type_uuid",
name=op.f("uq_land_asset_land_type_uuid"),
postgresql_include=[],
postgresql_nulls_not_distinct=False,
),
sa.UniqueConstraint(
"name",
name=op.f("uq_land_asset_name"),
postgresql_include=[],
postgresql_nulls_not_distinct=False,
),
)
op.create_table(
"land_asset_version",
sa.Column("uuid", sa.UUID(), autoincrement=False, nullable=False),
sa.Column("name", sa.VARCHAR(length=100), autoincrement=False, nullable=True),
sa.Column("land_type_uuid", sa.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("archived", sa.BOOLEAN(), autoincrement=False, nullable=True),
sa.Column("farmos_uuid", sa.UUID(), autoincrement=False, nullable=True),
sa.Column("drupal_id", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column("transaction_id", sa.BIGINT(), autoincrement=False, nullable=False),
sa.Column(
"end_transaction_id", sa.BIGINT(), autoincrement=False, nullable=True
),
sa.Column("operation_type", sa.SMALLINT(), autoincrement=False, nullable=False),
sa.PrimaryKeyConstraint(
"uuid", "transaction_id", name=op.f("pk_land_asset_version")
),
)
op.create_index(
op.f("ix_land_asset_version_transaction_id"),
"land_asset_version",
["transaction_id"],
unique=False,
)
op.create_index(
op.f("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_pk_transaction_id"),
"land_asset_version",
["uuid", sa.literal_column("transaction_id DESC")],
unique=False,
)
op.create_index(
op.f("ix_land_asset_version_operation_type"),
"land_asset_version",
["operation_type"],
unique=False,
)
op.create_index(
op.f("ix_land_asset_version_end_transaction_id"),
"land_asset_version",
["end_transaction_id"],
unique=False,
)
# land_asset_parent
op.create_table(
"land_asset_parent",
sa.Column("uuid", sa.UUID(), autoincrement=False, nullable=False),
sa.Column("land_asset_uuid", sa.UUID(), autoincrement=False, nullable=False),
sa.Column("parent_asset_uuid", sa.UUID(), autoincrement=False, nullable=False),
sa.ForeignKeyConstraint(
["land_asset_uuid"],
["land_asset.uuid"],
name=op.f("fk_land_asset_parent_land_asset_uuid_land_asset"),
),
sa.ForeignKeyConstraint(
["parent_asset_uuid"],
["land_asset.uuid"],
name=op.f("fk_land_asset_parent_parent_asset_uuid_land_asset"),
),
sa.PrimaryKeyConstraint("uuid", name=op.f("pk_land_asset_parent")),
)
op.create_table(
"land_asset_parent_version",
sa.Column("uuid", sa.UUID(), autoincrement=False, nullable=False),
sa.Column("land_asset_uuid", sa.UUID(), autoincrement=False, nullable=True),
sa.Column("parent_asset_uuid", sa.UUID(), autoincrement=False, nullable=True),
sa.Column("transaction_id", sa.BIGINT(), autoincrement=False, nullable=False),
sa.Column(
"end_transaction_id", sa.BIGINT(), autoincrement=False, nullable=True
),
sa.Column("operation_type", sa.SMALLINT(), autoincrement=False, nullable=False),
sa.PrimaryKeyConstraint(
"uuid", "transaction_id", name=op.f("pk_land_asset_parent_version")
),
)
op.create_index(
op.f("ix_land_asset_parent_version_transaction_id"),
"land_asset_parent_version",
["transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_land_asset_parent_version_pk_validity"),
"land_asset_parent_version",
["uuid", "transaction_id", "end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_land_asset_parent_version_pk_transaction_id"),
"land_asset_parent_version",
["uuid", sa.literal_column("transaction_id DESC")],
unique=False,
)
op.create_index(
op.f("ix_land_asset_parent_version_operation_type"),
"land_asset_parent_version",
["operation_type"],
unique=False,
)
op.create_index(
op.f("ix_land_asset_parent_version_end_transaction_id"),
"land_asset_parent_version",
["end_transaction_id"],
unique=False,
)
# asset_land
op.drop_table("asset_land")
op.drop_index(
op.f("ix_asset_land_version_transaction_id"), table_name="asset_land_version"
)
op.drop_index("ix_asset_land_version_pk_validity", table_name="asset_land_version")
op.drop_index(
"ix_asset_land_version_pk_transaction_id", table_name="asset_land_version"
)
op.drop_index(
op.f("ix_asset_land_version_operation_type"), table_name="asset_land_version"
)
op.drop_index(
op.f("ix_asset_land_version_end_transaction_id"),
table_name="asset_land_version",
)
op.drop_table("asset_land_version")
# asset_parent
op.drop_index(
op.f("ix_asset_parent_version_transaction_id"),
table_name="asset_parent_version",
)
op.drop_index(
"ix_asset_parent_version_pk_validity", table_name="asset_parent_version"
)
op.drop_index(
"ix_asset_parent_version_pk_transaction_id", table_name="asset_parent_version"
)
op.drop_index(
op.f("ix_asset_parent_version_operation_type"),
table_name="asset_parent_version",
)
op.drop_index(
op.f("ix_asset_parent_version_end_transaction_id"),
table_name="asset_parent_version",
)
op.drop_table("asset_parent_version")
op.drop_table("asset_parent")

View file

@ -1,206 +0,0 @@
"""add generic log base
Revision ID: dd6351e69233
Revises: b8cd4a8f981f
Create Date: 2026-02-18 12:09:05.200134
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
import wuttjamaican.db.util
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
revision: str = "dd6351e69233"
down_revision: Union[str, None] = "b8cd4a8f981f"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# log
op.create_table(
"log",
sa.Column("uuid", wuttjamaican.db.util.UUID(), nullable=False),
sa.Column("log_type", sa.String(length=100), 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.ForeignKeyConstraint(
["log_type"], ["log_type.drupal_id"], name=op.f("fk_log_log_type_log_type")
),
sa.PrimaryKeyConstraint("uuid", name=op.f("pk_log")),
sa.UniqueConstraint("drupal_id", name=op.f("uq_log_drupal_id")),
sa.UniqueConstraint("farmos_uuid", name=op.f("uq_log_farmos_uuid")),
)
op.create_table(
"log_version",
sa.Column(
"uuid", wuttjamaican.db.util.UUID(), autoincrement=False, nullable=False
),
sa.Column(
"log_type", sa.String(length=100), autoincrement=False, nullable=True
),
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_version")),
)
op.create_index(
op.f("ix_log_version_end_transaction_id"),
"log_version",
["end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_log_version_operation_type"),
"log_version",
["operation_type"],
unique=False,
)
op.create_index(
"ix_log_version_pk_transaction_id",
"log_version",
["uuid", sa.literal_column("transaction_id DESC")],
unique=False,
)
op.create_index(
"ix_log_version_pk_validity",
"log_version",
["uuid", "transaction_id", "end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_log_version_transaction_id"),
"log_version",
["transaction_id"],
unique=False,
)
# log_activity
op.drop_column("log_activity_version", "status")
op.drop_column("log_activity_version", "farmos_uuid")
op.drop_column("log_activity_version", "timestamp")
op.drop_column("log_activity_version", "message")
op.drop_column("log_activity_version", "drupal_id")
op.drop_column("log_activity_version", "notes")
op.drop_constraint(
op.f("uq_log_activity_drupal_id"), "log_activity", type_="unique"
)
op.drop_constraint(
op.f("uq_log_activity_farmos_uuid"), "log_activity", type_="unique"
)
op.create_foreign_key(
op.f("fk_log_activity_uuid_log"), "log_activity", "log", ["uuid"], ["uuid"]
)
op.drop_column("log_activity", "status")
op.drop_column("log_activity", "farmos_uuid")
op.drop_column("log_activity", "timestamp")
op.drop_column("log_activity", "message")
op.drop_column("log_activity", "drupal_id")
op.drop_column("log_activity", "notes")
def downgrade() -> None:
# log_activity
op.add_column(
"log_activity",
sa.Column("notes", sa.TEXT(), autoincrement=False, nullable=True),
)
op.add_column(
"log_activity",
sa.Column("drupal_id", sa.INTEGER(), autoincrement=False, nullable=True),
)
op.add_column(
"log_activity",
sa.Column(
"message", sa.VARCHAR(length=255), autoincrement=False, nullable=False
),
)
op.add_column(
"log_activity",
sa.Column(
"timestamp", postgresql.TIMESTAMP(), autoincrement=False, nullable=False
),
)
op.add_column(
"log_activity",
sa.Column("farmos_uuid", sa.UUID(), autoincrement=False, nullable=True),
)
op.add_column(
"log_activity",
sa.Column("status", sa.VARCHAR(length=20), autoincrement=False, nullable=False),
)
op.drop_constraint(
op.f("fk_log_activity_uuid_log"), "log_activity", type_="foreignkey"
)
op.create_unique_constraint(
op.f("uq_log_activity_farmos_uuid"),
"log_activity",
["farmos_uuid"],
postgresql_nulls_not_distinct=False,
)
op.create_unique_constraint(
op.f("uq_log_activity_drupal_id"),
"log_activity",
["drupal_id"],
postgresql_nulls_not_distinct=False,
)
op.add_column(
"log_activity_version",
sa.Column("notes", sa.TEXT(), autoincrement=False, nullable=True),
)
op.add_column(
"log_activity_version",
sa.Column("drupal_id", sa.INTEGER(), autoincrement=False, nullable=True),
)
op.add_column(
"log_activity_version",
sa.Column(
"message", sa.VARCHAR(length=255), autoincrement=False, nullable=True
),
)
op.add_column(
"log_activity_version",
sa.Column(
"timestamp", postgresql.TIMESTAMP(), autoincrement=False, nullable=True
),
)
op.add_column(
"log_activity_version",
sa.Column("farmos_uuid", sa.UUID(), autoincrement=False, nullable=True),
)
op.add_column(
"log_activity_version",
sa.Column("status", sa.VARCHAR(length=20), autoincrement=False, nullable=True),
)
# log
op.drop_index(op.f("ix_log_version_transaction_id"), table_name="log_version")
op.drop_index("ix_log_version_pk_validity", table_name="log_version")
op.drop_index("ix_log_version_pk_transaction_id", table_name="log_version")
op.drop_index(op.f("ix_log_version_operation_type"), table_name="log_version")
op.drop_index(op.f("ix_log_version_end_transaction_id"), table_name="log_version")
op.drop_table("log_version")
op.drop_table("log")

View file

@ -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")

View file

@ -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")

View file

@ -1,102 +0,0 @@
"""add Units
Revision ID: ea88e72a5fa5
Revises: 82a03f4ef1a4
Create Date: 2026-02-18 20:01:40.720138
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
import wuttjamaican.db.util
# revision identifiers, used by Alembic.
revision: str = "ea88e72a5fa5"
down_revision: Union[str, None] = "82a03f4ef1a4"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# unit
op.create_table(
"unit",
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.Integer(), nullable=True),
sa.PrimaryKeyConstraint("uuid", name=op.f("pk_unit")),
sa.UniqueConstraint("drupal_id", name=op.f("uq_unit_drupal_id")),
sa.UniqueConstraint("farmos_uuid", name=op.f("uq_unit_farmos_uuid")),
sa.UniqueConstraint("name", name=op.f("uq_unit_name")),
)
op.create_table(
"unit_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_unit_version")),
)
op.create_index(
op.f("ix_unit_version_end_transaction_id"),
"unit_version",
["end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_unit_version_operation_type"),
"unit_version",
["operation_type"],
unique=False,
)
op.create_index(
"ix_unit_version_pk_transaction_id",
"unit_version",
["uuid", sa.literal_column("transaction_id DESC")],
unique=False,
)
op.create_index(
"ix_unit_version_pk_validity",
"unit_version",
["uuid", "transaction_id", "end_transaction_id"],
unique=False,
)
op.create_index(
op.f("ix_unit_version_transaction_id"),
"unit_version",
["transaction_id"],
unique=False,
)
def downgrade() -> None:
# unit
op.drop_index(op.f("ix_unit_version_transaction_id"), table_name="unit_version")
op.drop_index("ix_unit_version_pk_validity", table_name="unit_version")
op.drop_index("ix_unit_version_pk_transaction_id", table_name="unit_version")
op.drop_index(op.f("ix_unit_version_operation_type"), table_name="unit_version")
op.drop_index(op.f("ix_unit_version_end_transaction_id"), table_name="unit_version")
op.drop_table("unit_version")
op.drop_table("unit")

View file

@ -1,39 +0,0 @@
"""add Log.is_group_assignment
Revision ID: f3c7e273bfa3
Revises: 47d0ebd84554
Create Date: 2026-02-28 20:04:40.700474
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
import wuttjamaican.db.util
# revision identifiers, used by Alembic.
revision: str = "f3c7e273bfa3"
down_revision: Union[str, None] = "47d0ebd84554"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# log
op.add_column("log", sa.Column("is_group_assignment", sa.Boolean(), nullable=True))
op.add_column(
"log_version",
sa.Column(
"is_group_assignment", sa.Boolean(), autoincrement=False, nullable=True
),
)
def downgrade() -> None:
# log
op.drop_column("log_version", "is_group_assignment")
op.drop_column("log", "is_group_assignment")

View file

@ -26,20 +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 .unit import Unit, Measure
from .quantities import QuantityType, Quantity, StandardQuantity
from .asset import AssetType, Asset, AssetParent
from .asset_land import LandType, LandAsset
from .asset_structure import StructureType, StructureAsset
from .asset_animal import AnimalType, AnimalAsset
from .asset_group import GroupAsset
from .asset_plant import PlantType, PlantAsset, PlantAssetPlantType
from .log import LogType, Log, LogAsset, LogGroup, LogLocation, LogQuantity, LogOwner
from .log_activity import ActivityLog
from .log_harvest import HarvestLog
from .log_medical import MedicalLog
from .log_observation import ObservationLog
# TODO: import other/custom models here...

Some files were not shown because too many files have changed in this diff Show more