Termination events

So in the work I’m doing, termination is an important and useful term to describe when a planting is truly ‘done’. Harvest is often associated with termination (cutting wheat, for example), but termination is uniquely helpful because it sets a concrete end to a planting which may not have one.

This is important in my world because we’re very interested in comparability and benchmarking, and turns out termination is really important in being able to bookend a planting, and therefore the management decisions made around that planting.

Here’s some cases where termination is important:

  1. I may leave a green cover crop on over winter, and actively terminate it in the spring with tillage or herbicide, or I may simply plant into it directly with my next seeding. These are all types of termination.
  2. I may have multiple harvests from kale over the year, but actively pull out the plants in winter.
  3. I may till under or use herbicide on a alfalfa crop (multi-year) to prep it for a different crop next year.
  4. I may remove fruit trees.

termination could simply be considered archiving a planting, but right now archiving doesn’t have an associated date - it is just a flag. It’s important to have a date.

So I would propose a unique log type called termination which acts similarly to seeding in that it is a log itself, but it also automatically archives the planting it’s associated with (similar to how seeding automatically attributes its geometry to the plant asset. There’s questions here about how sticky that is… like as long as there’s a termination, does it enforce the archive flag, or just check it one time (allowing me to uncheck)… etc.

In this world, I could simply add a termination log when I wanted - in conjunction with a final harvest event, or separately as in the cases above.

Any thoughts or ideas on this? Has there been thoughts in this direction?


Archiving does have a date, but the date just isn’t shown the UI (and can’t be set by the user) at the moment.

Obviously, it is also already possible to provide a revision comment as part of the asset update that archives it.

So the simplest change might just be to expose the archived date in the UI.

More broadly though, I think something like this could be useful when there is additional (structured) data that needs to be associated with the transition of an asset to the archived state. I think @Farmer-Ed has some log types like this for his animals.

This also reminds me a bit of what I was alluding to with the “axioms” I wrote out in this post.

i.e. the concept that more fields on assets could (in theory) be generalized to be the result of the associated logs - just like inventory, group membership, and location/geometry are today.

I’m a little less sold on that generalization making sense for all fields now (given how much complexity the existing cases already hold and that asset versioning is on by default in farmOS), but perhaps archived date is a special case.


There has been some prior discussion about “termination” and/or “death” logs… and/or the need for something more explicit to indicate the “end of life” of an asset more generally. I’ll try to dig up some of the old threads and link them here.

The “archived” timestamp does exist, and could certainly be used as part of a convention to represent termination, but it isn’t very explicit. Archived could also have more meanings than just end of life, for example if you sell an animal you will most likely want to archive it, but it’s not dead. Also worth noting: if you unarchive and re-archive an asset, the timestamp gets changed automatically.

I think in most cases, the best is to have a log that represents EOL/termination, in the same way that Seeding or Birth logs are used to represent their beginning (as @gbathree said). Maybe a new dedicated log type would make sense… but I could also see the need for using existing log types to denote the same kind of event. For example, a Harvest log can also be the termination event. Or an Observation log (eg: if a flood wiped out a crop).

I think we haven’t proposed a definitive answer to this question in the past precisely because there’s so many possibilities. :slight_smile:

That doesn’t mean you can’t create a termination log in a module, and use that as part of your own convention in the meantime, @gbathree! But it would be great if we could come up with a good general purpose convention for this in farmOS core.

Here are some other threads on this topic:

In almost all of those, I point back to the top one as the “canonical” idea for solving it: https://www.drupal.org/project/farm/issues/2630218

Add a concept of “lifespan” to assets, similar to “location”, “group membership”, etc - and allow it to be tracked via logs. So one log can define the start of an asset’s life, and one can define the end.

1 Like

It also makes me think about the generalized “Traits” idea that @Symbioquine has brought up in the past (can’t find the original thread)… basically allowing any kind of key/value to be assigned to assets via logs, and updated by future logs.

With something like that, the “termination date” of an asset could be set via any log that references the asset, in theory.

1 Like

If I understand “Traits” correctly, would that be like a generalized case for what seeding does (assigning the location)? I think that does make sense, basically it’s a generalized asset modifier. (different idea but) It could be represented similar to the ‘is movement’ flag… so ‘is seeding’ would do the location swap, ‘is termination’ would archive and assign an archive date (or a different date field if that’s the wrong one). To me as an outside observer, these all feel similar.


Yes, I added Animal Death and Animal Purchase types to my instance. It just makes reports for those events simpler, for the accountant and Dept of Ag inspections.

1 Like

Sounds interesting
There is potentially 3 types of termination dates for Livestock and it’s nice to distinguish them.
A simple Termination or Archive Date is not enough, obviously it’s possible to distinguish in Logs, but those logs need to be separated too either by a log type or flag or other mechanism.

  1. Death on Farm
  2. Sale
  3. Slaughter on Farm
1 Like

Yes something like that…

The only oddball is the “archiving the asset” part.

Right now… when you create a movement log that moves an asset to a new location (via the is_movement boolean on the log), the asset itself is not actually modified at all (eg: the asset entity is not loaded, modified, and saved). Asset location is a special property of the asset that is calculated based on the history of all of that asset’s logs, but not actually saved anywhere in the database. The “status” of an asset (active vs archived) is a direct property of the asset (just like “done” / “pending” status is a property of logs). So making the asset “archived” when you assign a “termination date” trait via a log would be a bit more than how location works now, but it does make sense. We could have some additional logic that does that automatically.

There hasn’t been much thought given to the technical implementation of traits yet… might be time to open a new forum topic to discuss those options (and hopefully dig up the old conversations as well).

Was it this IRC logs for #farmOS, 2021-02-10 (GMT) | irc.farmos.org ?

I believe the concept of “Traits” I’ve proposed in the past was different. I’ve been interested for a while in tracking genetic/phenotypic traits - and modelling the ontology of trait types perhaps with reference to an external ontology identifier (example).

The generalization of asset field values being defined as a function of associated logs could be really interesting/useful too, I’d just argue for referring to it with a different term than “Traits”. :nerd_face:


I like the idea, of treating them like locations or
as actual “off farm” locations a final movement to “mart”, “abattoir” or “knackery”.

1 Like

Ah fair enough! Agreed “traits” is better for tracking genetic/phenotypic traits. :slight_smile:

Open to ideas for what to call this instead… but we should start a new thread I think - we’re getting off the “termination events” topic.

1 Like

One more thing :
A termination of something could also be planned after an event or at a specific date.


Do you think we could have a standard ‘termination’ log which at the core works for animals or plants, but then has categories (similar to land type maybe). This would be useful if the category is knowable and generalizable… I feel like for Plants it is, termination can be grouped pretty clearly for 99% of the cases… don’t know if that’s true for animals also. Otherwise, perhaps we use Tags and then apply a convention, but that feels appropriate only if we can’t effectively generalize to a significant majority of cases.


Sure could! I would probably recommend starting that in a custom module to experiment with it… as a short-term solution at least. In the same way that @Farmer-Ed created his own “Animal Death” log type. OR: use the existing harvest / activity log types and just follow your own convention of creating a log with the same timestamp as the archived timestamp (via API) and matching them up that way.

It feels like ultimately we should aim for the “asset properties tracked via logs” feature described above (formerly/improperly referred to by me as “traits” :slight_smile:) as the long-term solution. I feel like the log type shouldn’t be the only determining factor for defining “asset lifespan”. It feels artificially constraining - and adds the burden of creating multiple records to signify a single event (eg: 1 harvest log + 1 termination log). It seems like it would be more elegant to allow any log type to be used to set an asset’s “termination date” property.

Ultimately what we’re talking about here is how to represent termination date in a convention. That convention can change over time, as the features available to us change. So maybe the short term solution is to create a simple convention using the existing types/fields, and plan ahead to migrating that to use the new dynamic asset properties feature when it’s available.

Related: Documenting conventions


That all feels right to me - any log should click the termination box on an asset (that may be metaphorically, not sure how exactly it’d work under the hood), and the termination date and time should be stored. There is a question about if something is ‘unterminated’ and ‘reterminated’ but to me that’s an edge case.

For now, I’m using a log with log_category: termination to track this, and then archiving the asset at the same time… so a manual version basically.

1 Like

I’ve created a custom module adding asset termination farmOS Asset Termination | Drupal.org.

It works in the following way:

  • any log can be marked as termination by checking ‘Is termination’ field
  • on completion of termination log, all referenced assets are archived
  • every asset with completed termination log will display ‘Terminated’ field with value of termination datetime linked to termination log


  • every termination log will have automatically assigned ‘Termination’ log category
  • on module install, all logs with already assigned ‘Termination’ log category will be automatically marked as termination

From a technical perspective, ‘Terminated’ field value is dynamically computed based on logs (with ‘Is termination’ option checked) assigned to the asset. It is set to entity reference to the log that terminated the asset and displayed with a custom formatter that displays the referenced log timestamp linked to the log entity and with a ‘title’ attribute set to the log title.


Sounds good,
I’ll give it a try

Edit: Just did quickly :smiley:
It wouldn’t install with composer for me. Perhaps I need to add the repo, but I didn’t think that necessary when hosted on Drupal’s Git Repo.

root@fee0119b9b36:/opt/drupal# composer require 'drupal/farm_asset_termination:^1.1'
./composer.json has been updated
Running composer update drupal/farm_asset_termination
Loading composer repositories with package information

Updating dependencies                                 
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Root composer.json requires drupal/farm_asset_termination ^1.1 -> satisfiable by drupal/farm_asset_termination[1.1.0, 1.x-dev].
    - drupal/farm_asset_termination[1.1.0, ..., 1.x-dev] require drupal/asset * -> could not be found in any version, there may be a typo in the package name.
Potential causes:
 - A typo in the package name
 - The package is not available in a stable-enough version according to your minimum-stability setting
   see <https://getcomposer.org/doc/04-schema.md#minimum-stability> for more details.
 - It's a private package and you forgot to add a custom repository to find it

Read <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.
Installation failed, reverting ./composer.json and ./composer.lock to their original content.

Anyway just installed manually and had it quick look. LGTM, does what it says on the tin. Will have a closer look later.

The issue with installation with composer seems to be caused by declaring dependency on farm:asset in the module .info.yml file.
Drupal composer packages repo (packages.drupal.org) automatically adds dependencies from .info.yml to composer.json of the module following the logic that if for given dependency there is a project with the same name on drupal.org then add it as required dependency. https://git.drupalcode.org/project/project_composer/-/blob/7.x-1.x/project_composer.module#L418-419
This causes the problem with dependency on farm:asset because there is an asset project on https://drupal.org/project/asset, so it is declared as a dependency and since it doesn’t have a version for drupal 9 it can’t be resolved.
Not really sure what is the best way to fix this. From what I can see on other contrib farmOS modules published to drupal.org other farmOS core modules that these contrib modules depend on often have the name prefixed with farm_ so maybe a good option would be to rename asset module to farm_asset, so it can be declared as dependency by contrib modules.