Conversation
…ation at dierlijke meste gebruiksnorm calculation
…r Natura2000 and GWBG has priority on NV-gebied
|
WalkthroughThis update introduces a timeout mechanism and improved error handling for fetch requests in nitrogen norm calculations. It adds a new check for Natura 2000 areas affecting derogation norms, refines the norm determination logic to prioritize Natura 2000 areas, and updates related tests and documentation. Version numbers and changelogs are incremented accordingly. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant NormCalculator
Client->>NormCalculator: getNL2025DierlijkeMestGebruiksNorm(input)
par Parallel Checks
NormCalculator->>NormCalculator: isFieldInNVGebied()
NormCalculator->>NormCalculator: isFieldInGWGBGebied()
NormCalculator->>NormCalculator: isFieldInNatura2000Gebied()
end
NormCalculator->>NormCalculator: Determine norm based on area checks (Natura 2000 > GWBG > NV > Default)
NormCalculator-->>Client: Return norm value and source
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~15–20 minutes Possibly related PRs
Suggested reviewers
Poem
Note 🔌 MCP (Model Context Protocol) integration is now available in Early Access!Pro users can now connect to remote MCP servers under the Integrations page to get reviews and chat conversations that understand additional development context. ✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #230 +/- ##
==========================================
- Coverage 93.02% 92.88% -0.15%
==========================================
Files 85 85
Lines 12812 12885 +73
Branches 1293 1294 +1
==========================================
+ Hits 11919 11968 +49
- Misses 891 915 +24
Partials 2 2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (6)
.changeset/warm-pants-rush.md (1)
5-5: Clarify wording & keep changeset titles consistent“norm for derogation in GWGB should be 170” reads okay but differs from the style used in the two companion changesets. For easier changelog generation consider a short imperative sentence, e.g.
Fix derogation norm for GWBG: 170 kg N/ha.changeset/shy-tools-matter.md (1)
5-5: Minor wording tweakThe sentence is a bit hard to parse. Something like
Add Natura 2000 proximity check to derogation norm calculationis shorter and matches the other entries.
.changeset/angry-rings-punch.md (1)
5-5: Grammar / clarityMaybe re-phrase to:
Give Natura 2000 and GWBG derogation norms priority over NV-gebied(singular “has” → “give” / “has priority” → “priority over”).
Purely cosmetic, ignore if your changelog generator normalises text.
fdm-calculator/src/norms/nl/2025/dierlijke-mest-gebruiksnorm.test.ts (1)
66-81: Test name no longer matches behaviourThe test label still says “default norm value” but the expectation is the adjusted derogation value 170. Rename to avoid confusion when scanning results.
fdm-calculator/src/norms/nl/2025/dierlijke-mest-gebruiksnorm.ts (2)
48-86: Duplicate helper – consider extracting a generic “geoContains” util
isFieldInNatura2000Gebiedrepeats the entire body ofisFieldInGWGBGebied. Factor out a parametrised helper that takes the dataset URL to keep maintenance overhead low and reduce bundle size.
88-113: Doc-comment outdatedThe remarks section still only mentions NV-gebied and 200 kg norms. Please update to include Natura 2000 & GWBG rules so generated docs stay trustworthy.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
.changeset/angry-rings-punch.md(1 hunks).changeset/shy-tools-matter.md(1 hunks).changeset/warm-pants-rush.md(1 hunks)fdm-calculator/src/norms/nl/2025/dierlijke-mest-gebruiksnorm.test.ts(2 hunks)fdm-calculator/src/norms/nl/2025/dierlijke-mest-gebruiksnorm.ts(2 hunks)
🧰 Additional context used
🧠 Learnings (8)
📓 Common learnings
Learnt from: SvenVw
PR: SvenVw/fdm#6
File: fdm-app/vite.config.ts:5-9
Timestamp: 2024-11-25T12:42:32.783Z
Learning: In the `fdm-app` project, SvenVw is preparing for migration to Remix v3 and may include type declarations or configurations for v3 features in advance, such as in `vite.config.ts`.
Learnt from: SvenVw
PR: SvenVw/fdm#194
File: fdm-core/src/harvest.ts:488-644
Timestamp: 2025-07-31T11:38:50.661Z
Learning: The validation logic in updateHarvest is intentionally different from checkHarvestDateCompability because updateHarvest is for updating existing harvests while checkHarvestDateCompability is for inserting new harvests. The insertion function includes checks that don't apply to updates, such as verifying no harvest already exists for "once" harvestable cultivations.
Learnt from: SvenVw
PR: SvenVw/fdm#156
File: fdm-calculator/src/norms/nl/2025/stikstofgebruiksnorm.ts:295-303
Timestamp: 2025-07-21T12:06:07.070Z
Learning: Functions in the fdm-calculator with "NL2025" in their names are specifically designed for Netherlands 2025 agricultural norms calculation and hardcoded 2025 dates are appropriate in this context, as different years would have separate calculation modules.
📚 Learning: 2025-07-21T12:06:07.070Z
Learnt from: SvenVw
PR: SvenVw/fdm#156
File: fdm-calculator/src/norms/nl/2025/stikstofgebruiksnorm.ts:295-303
Timestamp: 2025-07-21T12:06:07.070Z
Learning: Functions in the fdm-calculator with "NL2025" in their names are specifically designed for Netherlands 2025 agricultural norms calculation and hardcoded 2025 dates are appropriate in this context, as different years would have separate calculation modules.
Applied to files:
.changeset/angry-rings-punch.md.changeset/shy-tools-matter.mdfdm-calculator/src/norms/nl/2025/dierlijke-mest-gebruiksnorm.test.tsfdm-calculator/src/norms/nl/2025/dierlijke-mest-gebruiksnorm.ts
📚 Learning: 2025-02-14T09:56:37.606Z
Learnt from: SvenVw
PR: SvenVw/fdm#75
File: fdm-app/app/routes/farm.$b_id_farm.field.$b_id.fertilizer.tsx:68-71
Timestamp: 2025-02-14T09:56:37.606Z
Learning: The `calculateDose` function in `svenvw/fdm-calculator` is a synchronous function that includes built-in validation for negative application amounts and nutrient rates.
Applied to files:
.changeset/angry-rings-punch.md.changeset/shy-tools-matter.mdfdm-calculator/src/norms/nl/2025/dierlijke-mest-gebruiksnorm.ts
📚 Learning: 2024-11-25T12:42:32.783Z
Learnt from: SvenVw
PR: SvenVw/fdm#6
File: fdm-app/vite.config.ts:5-9
Timestamp: 2024-11-25T12:42:32.783Z
Learning: In the `fdm-app` project, SvenVw is preparing for migration to Remix v3 and may include type declarations or configurations for v3 features in advance, such as in `vite.config.ts`.
Applied to files:
.changeset/shy-tools-matter.md
📚 Learning: 2025-01-23T15:17:23.027Z
Learnt from: SvenVw
PR: SvenVw/fdm#49
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:208-208
Timestamp: 2025-01-23T15:17:23.027Z
Learning: The `addField` function in fdm-core should verify field creation within the same transaction by checking the existence of the field and all its required relations (field data, acquiring info, geometry) before resolving its promise.
Applied to files:
.changeset/shy-tools-matter.md
📚 Learning: 2025-01-23T15:17:23.028Z
Learnt from: SvenVw
PR: SvenVw/fdm#49
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:208-208
Timestamp: 2025-01-23T15:17:23.028Z
Learning: The `addField` function in fdm-core should use database transactions and field verification to ensure field availability before resolving its promise, eliminating the need for sleep workarounds.
Applied to files:
.changeset/shy-tools-matter.md
📚 Learning: 2025-01-31T15:05:14.310Z
Learnt from: SvenVw
PR: SvenVw/fdm#67
File: fdm-app/app/routes/farm.create.$b_id_farm.fields.$b_id.tsx:601-610
Timestamp: 2025-01-31T15:05:14.310Z
Learning: The `updateField` function in fdm-core has optional parameters after `fdm` and `b_id`. The TypeScript definitions might show 8 required parameters due to a potential version mismatch.
Applied to files:
fdm-calculator/src/norms/nl/2025/dierlijke-mest-gebruiksnorm.ts
📚 Learning: 2025-01-31T15:34:20.850Z
Learnt from: SvenVw
PR: SvenVw/fdm#67
File: fdm-app/app/routes/farm.create.$b_id_farm.fields.$b_id.tsx:601-610
Timestamp: 2025-01-31T15:34:20.850Z
Learning: The `updateField` function in fdm-core has optional parameters that don't need to be passed as undefined. Only `fdm` and `b_id` are required.
Applied to files:
fdm-calculator/src/norms/nl/2025/dierlijke-mest-gebruiksnorm.ts
🧬 Code Graph Analysis (2)
fdm-calculator/src/norms/nl/2025/dierlijke-mest-gebruiksnorm.test.ts (2)
fdm-calculator/src/norms/nl/2025/dierlijke-mest-gebruiksnorm.ts (1)
getNL2025DierlijkeMestGebruiksNorm(114-149)fdm-calculator/src/norms/nl/2025/types.d.ts (1)
NL2025NormsInput(14-25)
fdm-calculator/src/norms/nl/2025/dierlijke-mest-gebruiksnorm.ts (1)
fdm-core/src/index.ts (1)
Field(102-102)
There was a problem hiding this comment.
Actionable comments posted: 1
🔭 Outside diff range comments (1)
fdm-calculator/src/norms/nl/2025/dierlijke-mest-gebruiksnorm.ts (1)
21-26: Naming inconsistency: “GWGB” vs “GWBG”Domain term is “GWBG” (GrondWaterBeschermingsGebied). The exported function name uses “GWGB”, which can confuse usage/searches.
- Prefer renaming to
isFieldInGWBGGebiedand keeping a deprecated alias to avoid breaking consumers.As a non-breaking interim step, add an alias:
// Add near the bottom of this module export function isFieldInGWBGGebied( b_centroid: Field["b_centroid"], ): Promise<boolean> { return isFieldInGWGBGebied(b_centroid) }
🧹 Nitpick comments (4)
fdm-calculator/src/norms/nl/2025/stikstofgebruiksnorm.ts (1)
14-15: Avoid duplicating FETCH_TIMEOUT_MS across modulesThis constant now exists in multiple modules. Consider centralizing (e.g., a small shared http/constants module) to keep timeout policy consistent across the calculator and avoid drift.
fdm-calculator/src/norms/nl/2025/dierlijke-mest-gebruiksnorm.ts (3)
8-9: Avoid duplicating FETCH_TIMEOUT_MS across modulesSame note as in stikstofgebruiksnorm.ts: centralize the timeout constant to keep fetch behavior consistent.
30-40: Good: GWBG lookup hardened with Accept + timeout + cleanupConsistent with the other module; this should mitigate flakiness and long-hanging requests. Consider preserving the original error as a cause for easier debugging.
Minimal tweak to retain the original error:
-throw new Error(`Error querying GWGB-Gebied : ${String(err)}`) +throw new Error(`Error querying GWGB-Gebied : ${String(err)}`, { cause: err as any })Also applies to: 42-49, 50-58
61-71: Doc typos and clarity in Natura 2000 helper
- “natura200-gebieden” → “Natura 2000-gebieden”
- “within 100m buffer” → “within a 100 m buffer”
- Article/grammar tweaks for readability.
Apply this doc-only diff:
- * Determines if a field is located within a Natura 2000 in the Netherlands. + * Determines if a field is located within a Natura 2000 area in the Netherlands. * This is achieved by performing a spatial query against a vector file containing - * the boundaries of all natura200-gebieden, including the 100m buffer. + * the boundaries of all Natura 2000-gebieden, including a 100 m buffer. @@ - * @returns A promise that resolves to `true` if the field's centroid is found within an natura2000-gebied or within 100m buffer, + * @returns A promise that resolves to `true` if the field's centroid is found within a Natura 2000-gebied or within the 100 m buffer,
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
fdm-calculator/CHANGELOG.md(1 hunks)fdm-calculator/package.json(1 hunks)fdm-calculator/src/norms/nl/2025/dierlijke-mest-gebruiksnorm.test.ts(2 hunks)fdm-calculator/src/norms/nl/2025/dierlijke-mest-gebruiksnorm.ts(4 hunks)fdm-calculator/src/norms/nl/2025/stikstofgebruiksnorm.ts(3 hunks)
✅ Files skipped from review due to trivial changes (2)
- fdm-calculator/package.json
- fdm-calculator/CHANGELOG.md
🚧 Files skipped from review as they are similar to previous changes (1)
- fdm-calculator/src/norms/nl/2025/dierlijke-mest-gebruiksnorm.test.ts
🧰 Additional context used
🧠 Learnings (14)
📓 Common learnings
Learnt from: SvenVw
PR: SvenVw/fdm#156
File: fdm-calculator/src/norms/nl/2025/stikstofgebruiksnorm.ts:295-303
Timestamp: 2025-07-21T12:06:07.070Z
Learning: Functions in the fdm-calculator with "NL2025" in their names are specifically designed for Netherlands 2025 agricultural norms calculation and hardcoded 2025 dates are appropriate in this context, as different years would have separate calculation modules.
📚 Learning: 2025-07-21T12:06:07.070Z
Learnt from: SvenVw
PR: SvenVw/fdm#156
File: fdm-calculator/src/norms/nl/2025/stikstofgebruiksnorm.ts:295-303
Timestamp: 2025-07-21T12:06:07.070Z
Learning: Functions in the fdm-calculator with "NL2025" in their names are specifically designed for Netherlands 2025 agricultural norms calculation and hardcoded 2025 dates are appropriate in this context, as different years would have separate calculation modules.
Applied to files:
fdm-calculator/src/norms/nl/2025/stikstofgebruiksnorm.tsfdm-calculator/src/norms/nl/2025/dierlijke-mest-gebruiksnorm.ts
📚 Learning: 2025-01-31T15:05:14.310Z
Learnt from: SvenVw
PR: SvenVw/fdm#67
File: fdm-app/app/routes/farm.create.$b_id_farm.fields.$b_id.tsx:601-610
Timestamp: 2025-01-31T15:05:14.310Z
Learning: The `updateField` function in fdm-core has optional parameters after `fdm` and `b_id`. The TypeScript definitions might show 8 required parameters due to a potential version mismatch.
Applied to files:
fdm-calculator/src/norms/nl/2025/stikstofgebruiksnorm.tsfdm-calculator/src/norms/nl/2025/dierlijke-mest-gebruiksnorm.ts
📚 Learning: 2025-01-23T15:17:23.028Z
Learnt from: SvenVw
PR: SvenVw/fdm#49
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:208-208
Timestamp: 2025-01-23T15:17:23.028Z
Learning: The `addField` function in fdm-core should use database transactions and field verification to ensure field availability before resolving its promise, eliminating the need for sleep workarounds.
Applied to files:
fdm-calculator/src/norms/nl/2025/stikstofgebruiksnorm.tsfdm-calculator/src/norms/nl/2025/dierlijke-mest-gebruiksnorm.ts
📚 Learning: 2025-02-13T09:03:11.890Z
Learnt from: SvenVw
PR: SvenVw/fdm#71
File: fdm-app/app/routes/farm.create.$b_id_farm.cultivations.$b_lu_catalogue.crop.harvest._index.tsx:111-135
Timestamp: 2025-02-13T09:03:11.890Z
Learning: When adding multiple harvests in fdm-app, use Promise.all instead of Promise.allSettled to ensure atomic behavior - if one harvest addition fails, all should fail and rollback to maintain data consistency.
Applied to files:
fdm-calculator/src/norms/nl/2025/stikstofgebruiksnorm.tsfdm-calculator/src/norms/nl/2025/dierlijke-mest-gebruiksnorm.ts
📚 Learning: 2024-11-27T12:15:36.425Z
Learnt from: SvenVw
PR: SvenVw/fdm#9
File: fdm-data/src/cultivations/index.test.ts:57-59
Timestamp: 2024-11-27T12:15:36.425Z
Learning: In `fdm-data/src/cultivations/index.test.ts`, the `fdm` object created by `drizzle` does not have an `.end()` method. Cleanup code should not attempt to call `fdm.end();`.
Applied to files:
fdm-calculator/src/norms/nl/2025/dierlijke-mest-gebruiksnorm.ts
📚 Learning: 2025-01-23T15:17:23.027Z
Learnt from: SvenVw
PR: SvenVw/fdm#49
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:208-208
Timestamp: 2025-01-23T15:17:23.027Z
Learning: The `addField` function in fdm-core should verify field creation within the same transaction by checking the existence of the field and all its required relations (field data, acquiring info, geometry) before resolving its promise.
Applied to files:
fdm-calculator/src/norms/nl/2025/dierlijke-mest-gebruiksnorm.ts
📚 Learning: 2024-11-25T12:42:32.783Z
Learnt from: SvenVw
PR: SvenVw/fdm#6
File: fdm-app/vite.config.ts:5-9
Timestamp: 2024-11-25T12:42:32.783Z
Learning: In the `fdm-app` project, SvenVw is preparing for migration to Remix v3 and may include type declarations or configurations for v3 features in advance, such as in `vite.config.ts`.
Applied to files:
fdm-calculator/src/norms/nl/2025/dierlijke-mest-gebruiksnorm.ts
📚 Learning: 2025-02-24T10:49:54.523Z
Learnt from: SvenVw
PR: SvenVw/fdm#84
File: fdm-app/app/root.tsx:89-145
Timestamp: 2025-02-24T10:49:54.523Z
Learning: In the ErrorBoundary component of fdm-app/app/root.tsx, all client errors (400, 401, 403, 404) are intentionally displayed with a 404 status code for security purposes.
Applied to files:
fdm-calculator/src/norms/nl/2025/dierlijke-mest-gebruiksnorm.ts
📚 Learning: 2025-01-31T15:34:20.850Z
Learnt from: SvenVw
PR: SvenVw/fdm#67
File: fdm-app/app/routes/farm.create.$b_id_farm.fields.$b_id.tsx:601-610
Timestamp: 2025-01-31T15:34:20.850Z
Learning: The `updateField` function in fdm-core has optional parameters that don't need to be passed as undefined. Only `fdm` and `b_id` are required.
Applied to files:
fdm-calculator/src/norms/nl/2025/dierlijke-mest-gebruiksnorm.ts
📚 Learning: 2025-01-24T11:28:01.882Z
Learnt from: SvenVw
PR: SvenVw/fdm#49
File: fdm-app/app/routes/farm.create.$b_id_farm.atlas.tsx:208-208
Timestamp: 2025-01-24T11:28:01.882Z
Learning: The `addField` function in fdm-core should use database transactions to ensure atomicity, and since transactions provide ACID guarantees, awaiting the inserts is sufficient to ensure field availability - no additional verification queries are needed.
Applied to files:
fdm-calculator/src/norms/nl/2025/dierlijke-mest-gebruiksnorm.ts
📚 Learning: 2025-04-18T14:20:40.975Z
Learnt from: SvenVw
PR: SvenVw/fdm#124
File: fdm-core/src/db/schema-authn.ts:70-76
Timestamp: 2025-04-18T14:20:40.975Z
Learning: The organization schema in fdm-core/src/db/schema-authn.ts is managed by better-auth, and modifications to field constraints (like making the slug field non-nullable) should maintain compatibility with better-auth's expectations, even if application code assumes non-null values.
Applied to files:
fdm-calculator/src/norms/nl/2025/dierlijke-mest-gebruiksnorm.ts
📚 Learning: 2025-01-31T15:05:14.310Z
Learnt from: SvenVw
PR: SvenVw/fdm#67
File: fdm-app/app/routes/farm.create.$b_id_farm.fields.$b_id.tsx:601-610
Timestamp: 2025-01-31T15:05:14.310Z
Learning: The `updateField` function in fdm-core requires 8 parameters: fdm, b_id (required), and 6 optional parameters (b_name, b_id_source, b_geometry, b_acquiring_date, b_acquiring_method, b_discarding_date).
Applied to files:
fdm-calculator/src/norms/nl/2025/dierlijke-mest-gebruiksnorm.ts
📚 Learning: 2025-03-04T10:56:35.540Z
Learnt from: SvenVw
PR: SvenVw/fdm#88
File: fdm-calculator/src/doses/calculate-dose.ts:18-18
Timestamp: 2025-03-04T10:56:35.540Z
Learning: In the FDM calculator, fertilizer nutrient rates (p_n_rt, p_p_rt, p_k_rt) are measured in g/kg, and are converted to fractions by dividing by 10 during dose calculations.
Applied to files:
fdm-calculator/src/norms/nl/2025/dierlijke-mest-gebruiksnorm.ts
🧬 Code Graph Analysis (1)
fdm-calculator/src/norms/nl/2025/stikstofgebruiksnorm.ts (1)
fdm-calculator/src/norms/nl/2025/types.d.ts (1)
RegionKey(227-227)
🔇 Additional comments (4)
fdm-calculator/src/norms/nl/2025/stikstofgebruiksnorm.ts (1)
36-46: Good: robust fetch with Accept header, AbortController, and timer cleanupThe NV-gebied lookup now has explicit content negotiation, timeout with abort, clearer error messages, and a finally cleanup. This matches prior guidance and will reduce flaky behavior and hangs.
Also applies to: 48-55, 56-64
fdm-calculator/src/norms/nl/2025/dierlijke-mest-gebruiksnorm.ts (3)
72-110: Good: Natura 2000 proximity check mirrors GWBG implementationTimeout handling, Accept header, and feature parsing are consistent. LGTM.
148-153: Good: run NV/GWBG/Natura 2000 lookups in parallelUsing Promise.all here is the right choice and aligns with earlier suggestions to remove unnecessary latency.
159-168: Derogation prioritization logic looks correctPriority order (Natura 2000 → GWBG → NV → default) with values 170/170/190/200 matches the PR intent and tests. Clear and readable.
| const params = new URLSearchParams() | ||
| params.append("locations", `[[${longitude}, ${latitude}]]`) | ||
|
|
||
| const controller = new AbortController() | ||
| const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS) | ||
|
|
There was a problem hiding this comment.
Bug: getRegion may resolve undefined; throw when no feature/region
If no feature is returned, the function completes without returning/throwing even though it promises RegionKey. Downstream indexing with an undefined region will fail later and obscure the root cause. Throw a specific error when no region is found.
Apply this diff to ensure an explicit error is thrown when no region is found:
const json = await response.json()
- const feature = json?.[0]?.[0]
- if (feature) {
- return feature.region as RegionKey
- }
+ const feature = json?.[0]?.[0]
+ if (feature?.region) {
+ return feature.region as RegionKey
+ }
+ throw new Error("No Table2 region found for provided location")Also applies to: 99-107, 109-113, 114-121
🤖 Prompt for AI Agents
In fdm-calculator/src/norms/nl/2025/stikstofgebruiksnorm.ts around lines 92 to
97, the getRegion function may return undefined without throwing an error when
no feature or region is found, causing downstream failures. Modify the function
to explicitly check if the feature or region is undefined and throw a specific
error in that case. Apply similar checks and error throws in the code blocks
spanning lines 99-107, 109-113, and 114-121 to ensure consistent error handling
when no region is found.
Summary by CodeRabbit
Closes @229