diff --git a/CHANGELOG.md b/CHANGELOG.md index 781a26c..579fc2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,13 +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.11.3 (2026-05-04) - -### Fix - -- set material types when creating new log w/ material quantity -- split numerator/denominator for quantity values - ## v0.11.2 (2026-03-21) ### Fix diff --git a/docs/index.rst b/docs/index.rst index 89d3d70..be04bee 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -24,7 +24,6 @@ include: :maxdepth: 2 :caption: Documentation: - narr/intro narr/install narr/auth narr/features diff --git a/docs/narr/intro.rst b/docs/narr/intro.rst deleted file mode 100644 index 4466d25..0000000 --- a/docs/narr/intro.rst +++ /dev/null @@ -1,123 +0,0 @@ - -============== - Introduction -============== - -This page hopefully conveys the what and why of WuttaFarm as a project. - -WuttaFarm can serve as a "supplement" or "alternative" to `farmOS -`_, depending on your needs. It has 3 distinct -"modes" of operation: - -* :ref:`wrapper (API only) ` -* :ref:`mirror (2-way sync) ` -* :ref:`standalone ` - - -Rationale ---------- - -This project exists primarily to scratch a personal itch, but the hope -of course is that others will find it useful also. This is partly why -the app has different integration modes. - -Realistically this is not (yet?) meant to be a "finished" app per se. -In that sense it is akin to farmOS itself, i.e. "part app, part -framework" which can be extended where needed. - -It purposefully does not try to re-invent every wheel provided by -farmOS. But it does re-invent "certain types" of wheels, to some -degree, depending on which mode is used. - -It should also be mentioned, the 3 "modes" are essentially just -abstractions for sake of convenience. The framework allows one to -customize however you want regardless of the "mode" in effect. - -The target audience I suppose, is folks like me who prefer Python over -PHP, and can customize away without having to touch Drupal. - - -.. _wrapper-mode: - -Wrapper Mode (API only) ------------------------ - -This is the default integration mode for the app. In wrapper mode, -WuttaFarm UI will only expose views which display/modify farmOS data -*directly* via its JSONAPI. The app will not expose any views which -operate on its "native" tables (for assets, logs etc.). - -Any data model extensions needed must of course be managed on the -farmOS side, since the native tables are not used for this mode. - -This mode is simplest (for farmOS integration) since every user action -goes immeditely through the API. There is no "sync" or caching -involved. - -There is one known issue with this mode, and it's kind of a bummer: - -When viewing the "list" page for any record type (e.g. Animal Assets), -due to a quirk with the JSONAPI, you can only see the "first 50" -results in the listing. However you can still filter/sort the -records, to hopefully find what you need. And you can still view -*any* record if you have its URL (which you can normally figure out -from the farmOS UUID value). - - -.. _mirror-mode: - -Mirror Mode (2-way sync) ------------------------- - -This mode exposes the native table views in addition to direct API -views. It's sort of a combination of the wrapper and standalone -modes, with an extra daemon process to handle some of the sync tasks. - -(It's also the most complex mode to setup; more "moving parts" which -means potentially more to go wrong and require troubleshooting.) - -Again this depends on your actual use case, but a "complete" setup for -this mode would mean: - -* changes made in WuttaFarm are synced to farmOS via JSONAPI -* changes made in farmOS are synced to WuttaFarm via webhook+daemon - -The latter includes changes made via the farmOS proper web app, and/or -changes made via the "direct API" views within WuttaFarm (or anything -else that invokes the farmOS API). This requires the extra daemon -process (running alongside the WuttaFarm web app process), as well as -the `webhooks module -`_ on -the farmOS side. - -It's possible to extend the data model on the WuttaFarm side with or -without doing so on the farmOS side, and vice versa. Although -regardless you may have to take both into consideration for your -overall sync needs. - -There is support for "full" data import/export between systems in both -directions, WuttaFarm <=> farmOS. Limited of course by the common -schema they share etc. This can be leveraged easily to include -nightly "data diff" checks, ensuring all stays in sync. - - - -.. _standalone-mode: - -Standalone Mode ---------------- - -This mode exposes *only* the native table views, and none of the -"direct API" views. This requires no farmOS at all. - -This lets you customize the data model as needed, using SQLAlchemy and -Alembic, as does the mirror mode. However no "sync" is required so -you don't have to consider the farmOS data model. - -While the wrapper mode is simplest for farmOS integration, this -standalone mode is even simpler, technically speaking. It should work -well if you just need the basic record-keeping aspects. - -The main downside with this mode is there is not (yet?) any -mapping/geometry support, nor is there support for image/file -attachments. diff --git a/pyproject.toml b/pyproject.toml index 4012f79..b702d8c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "hatchling.build" [project] name = "WuttaFarm" -version = "0.11.3" +version = "0.11.2" description = "Web app to integrate with and extend farmOS" readme = "README.md" authors = [ diff --git a/src/wuttafarm/web/menus.py b/src/wuttafarm/web/menus.py index 62d3d9c..2756738 100644 --- a/src/wuttafarm/web/menus.py +++ b/src/wuttafarm/web/menus.py @@ -138,11 +138,6 @@ class WuttaFarmMenuHandler(base.MenuHandler): "route": "land_types", "perm": "land_types.list", }, - { - "title": "Material Types", - "route": "material_types", - "perm": "material_types.list", - }, { "title": "Plant Types", "route": "plant_types", @@ -223,6 +218,11 @@ class WuttaFarmMenuHandler(base.MenuHandler): "route": "log_types", "perm": "log_types.list", }, + { + "title": "Material Types", + "route": "material_types", + "perm": "material_types.list", + }, { "title": "Measures", "route": "measures", diff --git a/src/wuttafarm/web/templates/wuttafarm-components.mako b/src/wuttafarm/web/templates/wuttafarm-components.mako index b7c81c7..890568f 100644 --- a/src/wuttafarm/web/templates/wuttafarm-components.mako +++ b/src/wuttafarm/web/templates/wuttafarm-components.mako @@ -847,18 +847,12 @@ } const measureMap = {} - for (const m of this.measures) { + for (let m of this.measures) { measureMap[m.drupal_id] = m.name } - const quantityTypeMap = {} - for (const qt of this.quantityTypes) { - quantityTypeMap[qt.drupal_id] = qt.name - } - return { measureMap, - quantityTypeMap, quantityType: this.defaultQuantityType, editShowDialog: false, editNew: true, @@ -899,7 +893,8 @@ this.newQuantity.quantity_type = { drupal_id: this.quantityType, - name: this.quantityTypeMap[this.quantityType], + ## TODO: add support for other quantity types + name: "Standard", } this.newQuantity.measure = null diff --git a/src/wuttafarm/web/views/logs.py b/src/wuttafarm/web/views/logs.py index df2b01f..2a4e6e0 100644 --- a/src/wuttafarm/web/views/logs.py +++ b/src/wuttafarm/web/views/logs.py @@ -23,8 +23,6 @@ Base views for Logs """ -import decimal -import time from collections import OrderedDict import colander @@ -400,16 +398,13 @@ class LogMasterView(WuttaFarmMasterView): units = session.get(model.Unit, new_qty["units"]["uuid"]) assert units if new_qty["uuid"].startswith("new_"): - num, denom = decimal.Decimal(new_qty["value"]).as_integer_ratio() qty = self.app.make_true_quantity( new_qty["quantity_type"]["drupal_id"], measure_id=new_qty["measure"], - value_numerator=num, - value_denominator=denom, + value_numerator=int(new_qty["value"]), + value_denominator=1, units=units, ) - if qty.quantity_type_id == "material": - self.set_material_types(qty, new_qty["material_types"]) # nb. must ensure "typed" quantity record persists! session.add(qty) # but must add "generic" quantity record to log @@ -446,25 +441,18 @@ class LogMasterView(WuttaFarmMasterView): if old_mtype.uuid.hex not in desired: quantity.material_types.remove(old_mtype) - def auto_sync_to_farmos(self, client, uuid): + def auto_sync_to_farmos(self, client, log): model = self.app.model - model_class = self.get_model_class() + session = self.Session() - with self.app.short_session(commit=True) as session: - if user := session.query(model.User).filter_by(username="farmos").first(): - session.info["continuum_user_id"] = user.uuid + # nb. ensure quantities have uuid keys + session.flush() - log = None - while not log: - log = session.get(model_class, uuid) - if not log: - time.sleep(0.1) + for qty in log.quantities: + qty = self.app.get_true_quantity(qty) + self.app.auto_sync_to_farmos(qty, client=client) - for qty in log.quantities: - qty = self.app.get_true_quantity(qty) - self.app.auto_sync_to_farmos(qty, client=client) - - self.app.auto_sync_to_farmos(log, client=client) + self.app.auto_sync_to_farmos(log, client=client) def get_farmos_url(self, log): return self.app.get_farmos_url(f"/log/{log.drupal_id}")