Move vegetation strata from Crop to Planting (#86)#87
Merged
Conversation
Strata (the vertical layer / height) lived on `Crop`, so the same species at two training forms — e.g. apple basse-tige (shrub layer) vs mi-tige (understory) — forced a duplicate crop, and with it duplicate varieties. Move strata to the planting: one "Pommier" crop, one variety per cultivar, and the stratum chosen per planting. This matches agronomy (the form follows rootstock/training, decided at planting) and removes the duplication. - Domain: drop `strata_id` from `Crop`/`Crop::new`; add `strata_id` to `Planting`/`Planting::new`. - Migration 0004 (sqlite + mariadb): ALTER-only (no table rebuild). Add `planting.strata_id` (+ FK + index), backfill each row from its variety→crop stratum, then drop `crop.strata_id` (+ its index). Nullable at the DB level (the domain makes it mandatory; the backfill leaves no NULLs) to avoid an FK-enforced rebuild under the migrations' foreign_keys=ON. - DB layer: crop loses strata in COLUMNS/insert/update/row; planting gains it (same shape as the `status` column). - App: `create_annual_planting_from_sowing` / `create_perennial_planting` take a `strata_id`; `CropInput`/`CropRow` drop strata; `list_crops` no longer joins strata; `strata_view` in-use/delete guard now checks plantings (not crops); the crop-map split inherits the source planting's stratum. - UI: strata selector removed from the Cultures crop form and added to the Plantings form (annual + perennial); `strata_ids` on UiState now feeds the Plantings page; the planting create callbacks pass the chosen stratum. Tests: 326 green; strata-deletion guard test now seeds a planting; demo seeds each planting with a stratum. Migration verified on a real 0.9.0 DB — [1,2,3,4], crop has no strata column, planting strata backfilled to match the original crop stratum for all 7 plantings, zero NULLs; fresh seed-demo too. Closes #86. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #86.
Why
Strata (vertical layer / height) lived on
Crop. A species grown at two training forms — apple basse-tige (≈ Arbustive) vs mi-tige (≈ Sous-étage) — therefore needed a duplicate crop, and with it duplicate varieties. Surfaced in pre-prod testing while entering apple cultivars (Boskoop, Reinette grise…).Decision (validated)
Strata moves to the planting: one « Pommier » crop, one variety per cultivar, and the stratum chosen per planting. Agronomically correct (the form follows rootstock/training, decided at planting) and duplication-free.
Changes
strata_idremoved fromCrop/Crop::new, added toPlanting/Planting::new.planting.strata_id(+FK +index), backfills each row from itsvariety → cropstratum, then dropscrop.strata_id. Nullable at DB level (domain enforces presence; backfill leaves no NULLs) to avoid an FK-enforced rebuild under the migrations'foreign_keys=ON.statuscolumn pattern).create_*_plantingtake astrata_id;CropInput/CropRowdrop strata;list_cropsno longer joins strata;strata_viewin-use / delete guard now checks plantings; crop-map split inherits the source planting's stratum.Verification
cargo test --workspace(326),cargo clippy --workspace --all-targets,cargo fmt --check— all green.[1,2,3,4],crophas no strata column,planting.strata_idbackfilled to match the original crop stratum for all 7 plantings, zero NULLs.seed-demo: each planting seeded with a stratum (carrot→Racinaire, apple→Sous-étage, rest→Herbacée).Note: displaying the stratum on the planting list/detail rows was left as a small follow-up; the data and the form are in place.
🤖 Generated with Claude Code