From 8d7bf3f26700d764a8d253087e1b966dc47d035e Mon Sep 17 00:00:00 2001 From: SvenVw <37927107+SvenVw@users.noreply.github.com> Date: Wed, 15 Apr 2026 09:26:50 +0200 Subject: [PATCH 1/6] fix: bug in organic matter supply calculation where `undefined` crop residues yielded zero supply; it now correctly calculates supply for residues that are not explicitly removed. --- .../fix-fdm-calculator-m-cropresidue.md | 5 ++++ .../organic-matter/supply/residues.test.ts | 23 +++++++++++++++++++ .../balance/organic-matter/supply/residues.ts | 7 ++++-- 3 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 .changeset/fix-fdm-calculator-m-cropresidue.md diff --git a/.changeset/fix-fdm-calculator-m-cropresidue.md b/.changeset/fix-fdm-calculator-m-cropresidue.md new file mode 100644 index 000000000..ab12fbf59 --- /dev/null +++ b/.changeset/fix-fdm-calculator-m-cropresidue.md @@ -0,0 +1,5 @@ +--- +"@nmi-agro/fdm-calculator": patch +--- + +Fix a bug in organic matter supply calculation where `undefined` crop residues yielded zero supply; it now correctly calculates supply for residues that are not explicitly removed. diff --git a/fdm-calculator/src/balance/organic-matter/supply/residues.test.ts b/fdm-calculator/src/balance/organic-matter/supply/residues.test.ts index e884ea13e..72f2892cb 100644 --- a/fdm-calculator/src/balance/organic-matter/supply/residues.test.ts +++ b/fdm-calculator/src/balance/organic-matter/supply/residues.test.ts @@ -66,6 +66,29 @@ describe("calculateOrganicMatterSupplyByResidues", () => { }) }) + it("should calculate EOM supply from residues if m_cropresidue is undefined (standard practice)", () => { + const cultivations: FieldInput["cultivations"] = [ + { + b_lu: "cult1", + b_lu_catalogue: "maize", + m_cropresidue: undefined, + b_lu_end: new Date("2023-10-15"), + }, + ] as FieldInput["cultivations"] + + const result = calculateOrganicMatterSupplyByResidues( + cultivations, + cultivationDetailsMap, + timeFrame, + ) + + expect(result.total.toNumber()).toBe(800) + expect(result.cultivations[0]).toEqual({ + id: "cult1", + value: new Decimal(800), + }) + }) + it("should return zero if m_cropresidue is false", () => { const cultivations: FieldInput["cultivations"] = [ { diff --git a/fdm-calculator/src/balance/organic-matter/supply/residues.ts b/fdm-calculator/src/balance/organic-matter/supply/residues.ts index b13151e14..497b243df 100644 --- a/fdm-calculator/src/balance/organic-matter/supply/residues.ts +++ b/fdm-calculator/src/balance/organic-matter/supply/residues.ts @@ -35,8 +35,11 @@ export function calculateOrganicMatterSupplyByResidues( const cultivationDetail = cultivationDetailsMap.get(cult.b_lu_catalogue) // Proceed only if the cultivation type has a defined EOM value for residues - // and the 'm_cropresidue' flag is explicitly set to true. - if (cultivationDetail?.b_lu_eom_residue != null && cult.m_cropresidue) { + // and the 'm_cropresidue' flag is not explicitly set to false. + if ( + cultivationDetail?.b_lu_eom_residue != null && + cult.m_cropresidue !== false + ) { // Ensure the cultivation ended within the calculation timeframe. const terminationDate = cult.b_lu_end ? new Date(cult.b_lu_end) From 5db46b702d26669d0ce19b472774997e55047851 Mon Sep 17 00:00:00 2001 From: SvenVw <37927107+SvenVw@users.noreply.github.com> Date: Wed, 15 Apr 2026 09:27:16 +0200 Subject: [PATCH 2/6] test: add test for nitrogen balance when m_cropresidue is undefined --- .../balance/nitrogen/removal/residue.test.ts | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/fdm-calculator/src/balance/nitrogen/removal/residue.test.ts b/fdm-calculator/src/balance/nitrogen/removal/residue.test.ts index fa9b8538a..a038f8a00 100644 --- a/fdm-calculator/src/balance/nitrogen/removal/residue.test.ts +++ b/fdm-calculator/src/balance/nitrogen/removal/residue.test.ts @@ -254,6 +254,32 @@ describe("calculateNitrogenRemovalByResidue", () => { }) }) + it("should handle undefined m_cropresidue as not removed (return 0)", () => { + const cultivations: FieldInput["cultivations"] = [ + { + b_lu: "cultivation1", + b_lu_catalogue: "catalogue1", + b_lu_start: new Date("2022-01-01"), + b_lu_end: new Date("2022-12-31"), + m_cropresidue: undefined, // undefined residue handling + b_lu_name: "Cultivation 1", + b_lu_croprotation: "cereal", + }, + ] + const harvests: FieldInput["harvests"] = [] + + const result = calculateNitrogenRemovalByResidue( + cultivations, + harvests, + cultivationDetailsMap, + ) + + expect(result).toEqual({ + total: new Decimal(0), + cultivations: [{ id: "cultivation1", value: new Decimal(0) }], + }) + }) + it("should handle empty harvestable_analyses array", () => { const cultivations: FieldInput["cultivations"] = [ { From 6fd2c6312c08ef4ae3934761d6f5242b16c779a7 Mon Sep 17 00:00:00 2001 From: SvenVw <37927107+SvenVw@users.noreply.github.com> Date: Wed, 15 Apr 2026 09:27:35 +0200 Subject: [PATCH 3/6] fix: "Gewasresten achterlaten" input visibility to depend on crop rotation category (`b_lu_croprotation === 'cereal'`) and ensure its default value is `undefined` when hidden. --- .changeset/fix-fdm-app-m-cropresidue.md | 5 +++++ .../components/blocks/cultivation/card-details.tsx | 14 ++++++++------ fdm-app/app/components/blocks/rotation/columns.tsx | 2 +- 3 files changed, 14 insertions(+), 7 deletions(-) create mode 100644 .changeset/fix-fdm-app-m-cropresidue.md diff --git a/.changeset/fix-fdm-app-m-cropresidue.md b/.changeset/fix-fdm-app-m-cropresidue.md new file mode 100644 index 000000000..c82e4ad8e --- /dev/null +++ b/.changeset/fix-fdm-app-m-cropresidue.md @@ -0,0 +1,5 @@ +--- +"@nmi-agro/fdm-app": patch +--- + +Fix the "Gewasresten achterlaten" input visibility to depend on crop rotation category (`b_lu_croprotation === 'cereal'`) and ensure its default value is `undefined` when hidden. diff --git a/fdm-app/app/components/blocks/cultivation/card-details.tsx b/fdm-app/app/components/blocks/cultivation/card-details.tsx index 6cf22727d..9ca507889 100644 --- a/fdm-app/app/components/blocks/cultivation/card-details.tsx +++ b/fdm-app/app/components/blocks/cultivation/card-details.tsx @@ -47,8 +47,9 @@ export function CultivationDetailsCard({ ? new Date(cultivation.b_lu_end) : null, m_cropresidue: - !!cultivation.b_lu_eom_residue && - (cultivation.m_cropresidue ?? false), + cultivation.b_lu_croprotation === "cereal" + ? (cultivation.m_cropresidue ?? undefined) + : undefined, b_lu_variety: cultivation.b_lu_variety ?? null, }, }) @@ -63,8 +64,9 @@ export function CultivationDetailsCard({ ? new Date(cultivation.b_lu_end) : null, m_cropresidue: - !!cultivation.b_lu_eom_residue && - (cultivation.m_cropresidue ?? false), + cultivation.b_lu_croprotation === "cereal" + ? (cultivation.m_cropresidue ?? undefined) + : undefined, b_lu_variety: cultivation.b_lu_variety ?? null, }) }, [cultivation, form.reset]) @@ -135,8 +137,8 @@ export function CultivationDetailsCard({ diff --git a/fdm-app/app/components/blocks/rotation/columns.tsx b/fdm-app/app/components/blocks/rotation/columns.tsx index 7d28aa894..71e6de977 100644 --- a/fdm-app/app/components/blocks/rotation/columns.tsx +++ b/fdm-app/app/components/blocks/rotation/columns.tsx @@ -264,7 +264,7 @@ export const columns: ColumnDef[] = [ }, enableHiding: true, // Enable hiding for mobile cell: (props) => - (props.row.original.b_lu_eom_residue ?? 0) !== 0 && ( + props.row.original.b_lu_croprotation === "cereal" && ( ), }, From 4717bce1674970913a633e47fd2a28684c1e4174 Mon Sep 17 00:00:00 2001 From: SvenVw <37927107+SvenVw@users.noreply.github.com> Date: Wed, 15 Apr 2026 10:17:53 +0200 Subject: [PATCH 4/6] docs: update about m_cropresidue --- .../src/balance/organic-matter/supply/residues.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fdm-calculator/src/balance/organic-matter/supply/residues.ts b/fdm-calculator/src/balance/organic-matter/supply/residues.ts index 497b243df..3662b1e4f 100644 --- a/fdm-calculator/src/balance/organic-matter/supply/residues.ts +++ b/fdm-calculator/src/balance/organic-matter/supply/residues.ts @@ -11,8 +11,10 @@ import type { * * This function evaluates each cultivation to determine if its residues contribute to the soil's organic matter. * The contribution is only counted if two conditions are met: - * 1. The `m_cropresidue` flag for the cultivation is true, indicating that residues were incorporated into the soil. - * 2. The cultivation's end date (`b_lu_end`) falls within the specified calculation timeframe. + * 1. The `cultivationDetail.b_lu_eom_residue` value is present (not null or undefined) in the catalogue. + * 2. The `cult.m_cropresidue` flag is NOT explicitly set to `false`. This means residues are considered left + * on the field when `m_cropresidue` is either `true` or `undefined` (standard practice). + * 3. The cultivation's end date (`b_lu_end`) falls within the specified calculation timeframe. * * The EOM value for residues is sourced from the cultivation catalogue (`b_lu_eom_residue`). * From f6ca306603fd9451c8d70ae5f5bda0da7215f2b2 Mon Sep 17 00:00:00 2001 From: SvenVw <37927107+SvenVw@users.noreply.github.com> Date: Wed, 15 Apr 2026 10:45:43 +0200 Subject: [PATCH 5/6] fix: types --- fdm-calculator/src/balance/nitrogen/removal/residue.test.ts | 2 +- .../src/balance/organic-matter/supply/residues.test.ts | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/fdm-calculator/src/balance/nitrogen/removal/residue.test.ts b/fdm-calculator/src/balance/nitrogen/removal/residue.test.ts index a038f8a00..ab96d63ed 100644 --- a/fdm-calculator/src/balance/nitrogen/removal/residue.test.ts +++ b/fdm-calculator/src/balance/nitrogen/removal/residue.test.ts @@ -261,7 +261,7 @@ describe("calculateNitrogenRemovalByResidue", () => { b_lu_catalogue: "catalogue1", b_lu_start: new Date("2022-01-01"), b_lu_end: new Date("2022-12-31"), - m_cropresidue: undefined, // undefined residue handling + m_cropresidue: null, // null residue handling (represents undefined in UI) b_lu_name: "Cultivation 1", b_lu_croprotation: "cereal", }, diff --git a/fdm-calculator/src/balance/organic-matter/supply/residues.test.ts b/fdm-calculator/src/balance/organic-matter/supply/residues.test.ts index 72f2892cb..bf7502661 100644 --- a/fdm-calculator/src/balance/organic-matter/supply/residues.test.ts +++ b/fdm-calculator/src/balance/organic-matter/supply/residues.test.ts @@ -71,8 +71,10 @@ describe("calculateOrganicMatterSupplyByResidues", () => { { b_lu: "cult1", b_lu_catalogue: "maize", - m_cropresidue: undefined, + m_cropresidue: null, // null residue handling (represents undefined in UI) b_lu_end: new Date("2023-10-15"), + b_lu_name: "test", + b_lu_start: new Date("2023-05-01"), }, ] as FieldInput["cultivations"] From dee15e2d7314595ee99911cb0869641b43ba56a4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 16 Apr 2026 06:57:27 +0000 Subject: [PATCH 6/6] chore: bump version of packages for release --- .changeset/fix-fdm-app-m-cropresidue.md | 5 ----- .changeset/fix-fdm-calculator-m-cropresidue.md | 5 ----- fdm-app/CHANGELOG.md | 10 ++++++++++ fdm-app/package.json | 2 +- fdm-calculator/CHANGELOG.md | 6 ++++++ fdm-calculator/package.json | 2 +- 6 files changed, 18 insertions(+), 12 deletions(-) delete mode 100644 .changeset/fix-fdm-app-m-cropresidue.md delete mode 100644 .changeset/fix-fdm-calculator-m-cropresidue.md diff --git a/.changeset/fix-fdm-app-m-cropresidue.md b/.changeset/fix-fdm-app-m-cropresidue.md deleted file mode 100644 index c82e4ad8e..000000000 --- a/.changeset/fix-fdm-app-m-cropresidue.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@nmi-agro/fdm-app": patch ---- - -Fix the "Gewasresten achterlaten" input visibility to depend on crop rotation category (`b_lu_croprotation === 'cereal'`) and ensure its default value is `undefined` when hidden. diff --git a/.changeset/fix-fdm-calculator-m-cropresidue.md b/.changeset/fix-fdm-calculator-m-cropresidue.md deleted file mode 100644 index ab12fbf59..000000000 --- a/.changeset/fix-fdm-calculator-m-cropresidue.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@nmi-agro/fdm-calculator": patch ---- - -Fix a bug in organic matter supply calculation where `undefined` crop residues yielded zero supply; it now correctly calculates supply for residues that are not explicitly removed. diff --git a/fdm-app/CHANGELOG.md b/fdm-app/CHANGELOG.md index 85944f2e4..2b266056e 100644 --- a/fdm-app/CHANGELOG.md +++ b/fdm-app/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog fdm-app +## 0.29.5 + +### Patch Changes + +- [#569](https://github.com/nmi-agro/fdm/pull/569) [`6fd2c63`](https://github.com/nmi-agro/fdm/commit/6fd2c6312c08ef4ae3934761d6f5242b16c779a7) Thanks [@SvenVw](https://github.com/SvenVw)! - Fix the "Gewasresten achterlaten" input visibility to depend on crop rotation category (`b_lu_croprotation === 'cereal'`) and ensure its default value is `undefined` when hidden. + +- Updated dependencies [[`8d7bf3f`](https://github.com/nmi-agro/fdm/commit/8d7bf3f26700d764a8d253087e1b966dc47d035e)]: + - @nmi-agro/fdm-calculator@0.13.2 + - @nmi-agro/fdm-agents@0.2.1 + ## 0.29.4 ### Patch Changes diff --git a/fdm-app/package.json b/fdm-app/package.json index 142643f3d..a23478775 100644 --- a/fdm-app/package.json +++ b/fdm-app/package.json @@ -1,6 +1,6 @@ { "name": "@nmi-agro/fdm-app", - "version": "0.29.4", + "version": "0.29.5", "private": true, "sideEffects": false, "type": "module", diff --git a/fdm-calculator/CHANGELOG.md b/fdm-calculator/CHANGELOG.md index 44ea2347d..6f05c6c2f 100644 --- a/fdm-calculator/CHANGELOG.md +++ b/fdm-calculator/CHANGELOG.md @@ -1,5 +1,11 @@ # fdm-calculator +## 0.13.2 + +### Patch Changes + +- [#569](https://github.com/nmi-agro/fdm/pull/569) [`8d7bf3f`](https://github.com/nmi-agro/fdm/commit/8d7bf3f26700d764a8d253087e1b966dc47d035e) Thanks [@SvenVw](https://github.com/SvenVw)! - Fix a bug in organic matter supply calculation where `undefined` crop residues yielded zero supply; it now correctly calculates supply for residues that are not explicitly removed. + ## 0.13.1 ### Patch Changes diff --git a/fdm-calculator/package.json b/fdm-calculator/package.json index 85f982232..91ed15dd5 100644 --- a/fdm-calculator/package.json +++ b/fdm-calculator/package.json @@ -1,7 +1,7 @@ { "name": "@nmi-agro/fdm-calculator", "private": false, - "version": "0.13.1", + "version": "0.13.2", "description": "Calculate various insights based on the Farm Data Model", "license": "MIT", "homepage": "https://github.com/nmi-agro/fdm",