@agridea/suibi-module 0.1.0-preview.6 → 0.1.0-preview.68e6607
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -10
- package/dist/elements/browser/main.js +75 -72
- package/dist/elements/browser/styles.css +1 -1
- package/dist/elements/browser/suibi-module-latest.css +1 -1
- package/dist/elements/browser/suibi-module-latest.js +75 -72
- package/dist/elements/browser/{suibi-module.v0.1.0-preview.6.css → suibi-module.v0.1.0-preview.68e6607.css} +1 -1
- package/dist/elements/browser/suibi-module.v0.1.0-preview.68e6607.js +78 -0
- package/dist/elements/browser/suibi-theme-dark.css +1 -1
- package/dist/elements/browser/version.txt +1 -1
- package/dist/elements/browser/wc-global-utilities.css +1 -0
- package/dist/types/app/app.d.ts +1 -3
- package/dist/types/app/components/add-dashed-button/add-dashed-button.component.d.ts +9 -0
- package/dist/types/app/components/data-preview/data-preview.component.d.ts +4 -2
- package/dist/types/app/components/empty-state/empty-state.component.d.ts +12 -0
- package/dist/types/app/components/gauge-arc/gauge-arc.component.d.ts +49 -0
- package/dist/types/app/{header-bar.d.ts → components/header-bar/header-bar.component.d.ts} +3 -4
- package/dist/types/app/components/inline-table/inline-table.component.d.ts +114 -0
- package/dist/types/app/components/inline-table/inline-table.types.d.ts +161 -0
- package/dist/types/app/components/module-placeholder-page/module-placeholder-page.component.d.ts +6 -0
- package/dist/types/app/components/planning-result/planning-result.component.d.ts +46 -0
- package/dist/types/app/components/planning-result-row/planning-result-row.component.d.ts +34 -0
- package/dist/types/app/components/planning-trigger/planning-trigger.component.d.ts +13 -0
- package/dist/types/app/components/results-page/results-page.component.d.ts +13 -0
- package/dist/types/app/components/suissebilanz-dashboard/suissebilanz-dashboard.component.d.ts +32 -0
- package/dist/types/app/components/suissebilanz-dashboard/suissebilanz-metrics.service.d.ts +21 -0
- package/dist/types/app/components/suissebilanz-minibar/suissebilanz-minibar.component.d.ts +19 -0
- package/dist/types/app/components/validation-page/validation-page.component.d.ts +18 -0
- package/dist/types/app/components/welcome-page/metadata.types.d.ts +1 -1
- package/dist/types/app/components/welcome-page/welcome-page.component.d.ts +5 -3
- package/dist/types/app/components/workflow-stepper/workflow-stepper.component.d.ts +49 -0
- package/dist/types/app/core/data/naebi-data.service.d.ts +38 -28
- package/dist/types/app/core/error/global-error-handler.d.ts +2 -3
- package/dist/types/app/core/i18n/i18n.service.d.ts +5 -3
- package/dist/types/app/core/i18n/locales/fr.d.ts +2 -0
- package/dist/types/app/core/i18n/locales/it.d.ts +2 -0
- package/dist/types/app/core/master-data/master-data.service.d.ts +8 -1
- package/dist/types/app/core/metadata/suibi-metadata.types.d.ts +11 -1
- package/dist/types/app/core/navigation/navigation.service.d.ts +29 -1
- package/dist/types/app/core/planning/planning-balance.service.d.ts +38 -0
- package/dist/types/app/core/planning/planning-balance.types.d.ts +206 -0
- package/dist/types/app/core/planning/planning-balance.utils.d.ts +10 -0
- package/dist/types/app/core/utils/object.util.d.ts +26 -0
- package/dist/types/app/core/validation/capabilities.d.ts +5 -5
- package/dist/types/app/core/validation/global-validation.service.d.ts +19 -4
- package/dist/types/app/jsonforms/filters/code-list-filter-resolvers.d.ts +3 -0
- package/dist/types/app/jsonforms/registry/renderers.registry.d.ts +8 -0
- package/dist/types/app/jsonforms/renderers/controls/selects/animal-category/animal-category-select.renderer.d.ts +1 -1
- package/dist/types/app/jsonforms/renderers/controls/selects/code-list/code-list-select.renderer.d.ts +10 -4
- package/dist/types/app/jsonforms/renderers/layout/array/array-layout.renderer.d.ts +43 -0
- package/dist/types/app/jsonforms/renderers/layout/categorization/selected-category-categorization.renderer.d.ts +3 -0
- package/dist/types/app/jsonforms/renderers/layout/constraint/constraint-layout.renderer.d.ts +1 -0
- package/dist/types/app/jsonforms/renderers/layout/group/base-group.renderer.d.ts +2 -0
- package/dist/types/app/jsonforms/renderers/layout/group/module-toggle-group.renderer.d.ts +38 -0
- package/dist/types/app/nutrient-cycle/animal-stock/animal-stock-detail/animal-stock-detail.component.d.ts +21 -0
- package/dist/types/app/nutrient-cycle/animal-stock/{animal-stock-list.component.d.ts → animal-stock-list/animal-stock-list.component.d.ts} +6 -9
- package/dist/types/app/nutrient-cycle/animal-stock/{animal-stock-master-detail.component.d.ts → animal-stock-master-detail/animal-stock-master-detail.component.d.ts} +2 -3
- package/dist/types/app/nutrient-cycle/animal-stock/index.d.ts +3 -3
- package/dist/types/app/nutrient-cycle/farm-manure-trading/farm-manure-trading-detail/farm-manure-trading-detail.component.d.ts +26 -0
- package/dist/types/app/nutrient-cycle/farm-manure-trading/{farm-manure-trading-list.component.d.ts → farm-manure-trading-list/farm-manure-trading-list.component.d.ts} +9 -9
- package/dist/types/app/nutrient-cycle/farm-manure-trading/{farm-manure-trading-master-detail.component.d.ts → farm-manure-trading-master-detail/farm-manure-trading-master-detail.component.d.ts} +3 -4
- package/dist/types/app/nutrient-cycle/farm-manure-trading/index.d.ts +3 -3
- package/dist/types/app/nutrient-cycle/field-cultivation/arable-land-table/arable-land-table.component.d.ts +21 -0
- package/dist/types/app/nutrient-cycle/field-cultivation/arable-land-table/arable-land-table.config.d.ts +9 -0
- package/dist/types/app/nutrient-cycle/field-cultivation/crop-harvest-table/crop-harvest-table.component.d.ts +21 -0
- package/dist/types/app/nutrient-cycle/field-cultivation/crop-harvest-table/crop-harvest-table.config.d.ts +13 -0
- package/dist/types/app/nutrient-cycle/field-cultivation/field-cultivation-detail/field-cultivation-detail.component.d.ts +22 -0
- package/dist/types/app/nutrient-cycle/field-cultivation/field-cultivation-general/field-cultivation-general.component.d.ts +20 -0
- package/dist/types/app/nutrient-cycle/field-cultivation/field-cultivation-list/field-cultivation-list.component.d.ts +17 -0
- package/dist/types/app/nutrient-cycle/field-cultivation/field-cultivation-master-detail/field-cultivation-master-detail.component.d.ts +29 -0
- package/dist/types/app/nutrient-cycle/field-cultivation/field-cultivation.types.d.ts +41 -0
- package/dist/types/app/nutrient-cycle/field-cultivation/field-cultivation.util.d.ts +6 -0
- package/dist/types/app/nutrient-cycle/field-cultivation/fodder-cropland-table/fodder-cropland-table.component.d.ts +27 -0
- package/dist/types/app/nutrient-cycle/field-cultivation/fodder-cropland-table/fodder-cropland-table.config.d.ts +16 -0
- package/dist/types/app/nutrient-cycle/field-cultivation/index.d.ts +9 -0
- package/dist/types/app/nutrient-cycle/field-cultivation/special-crops-table/special-crops-table.component.d.ts +29 -0
- package/dist/types/app/nutrient-cycle/field-cultivation/special-crops-table/special-crops-table.config.d.ts +61 -0
- package/dist/types/app/nutrient-cycle/field-spreading/fertiliser-table/fertiliser-table.component.d.ts +43 -0
- package/dist/types/app/nutrient-cycle/field-spreading/fertiliser-table/fertiliser-table.config.d.ts +20 -0
- package/dist/types/app/nutrient-cycle/field-spreading/field-spreading.component.d.ts +16 -4
- package/dist/types/app/nutrient-cycle/field-spreading/ingredient.util.d.ts +8 -0
- package/dist/types/app/nutrient-cycle/field-spreading/recycling-table/recycling-table.component.d.ts +31 -0
- package/dist/types/app/nutrient-cycle/field-spreading/recycling-table/recycling-table.config.d.ts +17 -0
- package/dist/types/app/nutrient-cycle/field-spreading/recycling-table/recycling-transaction-unit.util.d.ts +4 -0
- package/dist/types/app/nutrient-cycle/fodder/fodder-master-detail/fodder-master-detail.component.d.ts +25 -0
- package/dist/types/app/nutrient-cycle/fodder/fodder-table/fodder-table.component.d.ts +26 -0
- package/dist/types/app/nutrient-cycle/fodder/fodder-table/fodder-table.config.d.ts +9 -0
- package/dist/types/app/nutrient-cycle/fodder/fodder.types.d.ts +34 -0
- package/dist/types/app/nutrient-cycle/fodder/index.d.ts +3 -0
- package/dist/types/app/nutrient-cycle/fodder/ingredient.util.d.ts +8 -0
- package/dist/types/app/nutrient-cycle/fodder/transaction-unit.util.d.ts +2 -0
- package/dist/types/app/nutrient-cycle/lifetime-performance/index.d.ts +2 -0
- package/dist/types/app/nutrient-cycle/lifetime-performance/lifetime-performance-form.component.d.ts +1 -1
- package/dist/types/app/nutrient-cycle/storage/index.d.ts +4 -0
- package/dist/types/app/nutrient-cycle/storage/storage-detail/storage-detail.component.d.ts +30 -0
- package/dist/types/app/nutrient-cycle/storage/storage-general/storage-general.component.d.ts +29 -0
- package/dist/types/app/nutrient-cycle/storage/storage-list/storage-list.component.d.ts +23 -0
- package/dist/types/app/nutrient-cycle/storage/storage-master-detail/storage-master-detail.component.d.ts +32 -0
- package/dist/types/app/nutrient-cycle/storage/storage.types.d.ts +40 -0
- package/dist/types/environments/environment.d.ts +5 -0
- package/dist/types/shared/material-icons.d.ts +3 -3
- package/package.json +68 -17
- package/dist/elements/browser/suibi-module.v0.1.0-preview.6.js +0 -75
- package/dist/types/app/nutrient-cycle/animal-stock/animal-stock-detail.component.d.ts +0 -22
- package/dist/types/app/nutrient-cycle/farm-manure-trading/farm-manure-trading-detail.component.d.ts +0 -27
- /package/dist/types/app/{core/validation/validation-errors-panel.d.ts → components/validation-errors-panel/validation-errors-panel.component.d.ts} +0 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ErrorObject } from 'ajv';
|
|
2
|
+
import { PlanningBalanceService } from '../../core/planning/planning-balance.service';
|
|
3
|
+
/**
|
|
4
|
+
* Final submission step: review validation status and submit the planning balance.
|
|
5
|
+
*/
|
|
6
|
+
export declare class ValidationPageComponent {
|
|
7
|
+
readonly showHeader: import("@angular/core").InputSignal<boolean>;
|
|
8
|
+
/** Navigation callback for validation error clicks — provided by App to keep routing logic centralised. */
|
|
9
|
+
readonly onErrorSelected: import("@angular/core").InputSignal<(error: ErrorObject) => void>;
|
|
10
|
+
/** Navigation callback triggered after a fresh successful planning submission. */
|
|
11
|
+
readonly onSubmitSuccess: import("@angular/core").InputSignal<() => void>;
|
|
12
|
+
protected readonly planning: PlanningBalanceService;
|
|
13
|
+
private readonly globalValidation;
|
|
14
|
+
private lastHandledSuccessRequestId;
|
|
15
|
+
constructor();
|
|
16
|
+
protected readonly validationErrors: import("@angular/core").Signal<import("../../../public-api").EnrichedValidationError[]>;
|
|
17
|
+
protected readonly errorCount: import("@angular/core").Signal<number>;
|
|
18
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { DEFAULT_SUIBI_METADATA, type SubmissionStatus, type SuibiVersion, type SuibiMetadata } from '../../core/metadata/suibi-metadata.types';
|
|
1
|
+
export { DEFAULT_SUIBI_METADATA, DEFAULT_COMPUTATION_MODULES, type ComputationModules, type SubmissionStatus, type SuibiVersion, type SuibiMetadata } from '../../core/metadata/suibi-metadata.types';
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { OnInit } from '@angular/core';
|
|
2
1
|
import { JsonSchema, UISchemaElement } from '@jsonforms/core';
|
|
3
2
|
import { SuibiMetadata } from '../../core/metadata/suibi-metadata.types';
|
|
4
|
-
export declare class WelcomePageComponent
|
|
3
|
+
export declare class WelcomePageComponent {
|
|
5
4
|
private readonly i18n;
|
|
6
5
|
private readonly metadataSvc;
|
|
6
|
+
private readonly naebi;
|
|
7
7
|
startEvent: import("@angular/core").OutputEmitterRef<void>;
|
|
8
8
|
metadataChange: import("@angular/core").OutputEmitterRef<SuibiMetadata>;
|
|
9
9
|
private readonly baseSchema;
|
|
@@ -17,11 +17,13 @@ export declare class WelcomePageComponent implements OnInit {
|
|
|
17
17
|
readonly localizedSchema: import("@angular/core").Signal<JsonSchema>;
|
|
18
18
|
readonly localizedUi: import("@angular/core").Signal<UISchemaElement>;
|
|
19
19
|
readonly jsonFormsData: import("@angular/core").Signal<{}>;
|
|
20
|
-
|
|
20
|
+
constructor();
|
|
21
21
|
start(): void;
|
|
22
|
+
loadExampleData(): void;
|
|
22
23
|
onMetadataChange(newValue: unknown): void;
|
|
23
24
|
private normalizeJsonFormsPayload;
|
|
24
25
|
private toMetadata;
|
|
26
|
+
private extractModules;
|
|
25
27
|
private isSuibiVersion;
|
|
26
28
|
private isSubmissionStatus;
|
|
27
29
|
private isSameMetadata;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { PageId } from '../../core/navigation/navigation.service';
|
|
2
|
+
/**
|
|
3
|
+
* WorkflowStepperComponent
|
|
4
|
+
* Horizontal navigation stepper for the main data-entry workflow.
|
|
5
|
+
*
|
|
6
|
+
* Design contract:
|
|
7
|
+
* - Uses mat-stepper as a header-only nav bar (step content is empty; content
|
|
8
|
+
* area is hidden via CSS so the stepper acts as a pure navigation indicator).
|
|
9
|
+
* - [selectedIndex] is driven by the currentPage input — no internal routing state.
|
|
10
|
+
* - Navigation is delegated back to App via the onNavigate callback, preserving
|
|
11
|
+
* the custom-element page-attribute reflection.
|
|
12
|
+
* - Error indicators: any page with at least one enriched validation error shows
|
|
13
|
+
* the error ring on its step circle. Requires STEPPER_GLOBAL_OPTIONS { showError: true }.
|
|
14
|
+
* - Non-workflow pages (e.g. data_preview): mat-stepper rejects out-of-bounds selectedIndex,
|
|
15
|
+
* so we clamp to 0; the no-active-step CSS class neutralises the visual active indicator,
|
|
16
|
+
* and onStepperClick delegates clicks for all headers (bypassing the stepper's
|
|
17
|
+
* "no-change" guard that suppresses selectedIndexChange for the currently selected step).
|
|
18
|
+
*
|
|
19
|
+
* Extension points:
|
|
20
|
+
* - Completed state: replace the hardcoded `false` on [completed] with a per-page
|
|
21
|
+
* computed once domain completion rules are defined (e.g. all required fields valid).
|
|
22
|
+
* - New pages: add an entry to WORKFLOW_STEPS and extend PageId.
|
|
23
|
+
*/
|
|
24
|
+
export declare class WorkflowStepperComponent {
|
|
25
|
+
protected readonly steps: readonly {
|
|
26
|
+
readonly pageId: PageId;
|
|
27
|
+
readonly labelKey: string;
|
|
28
|
+
}[];
|
|
29
|
+
/**
|
|
30
|
+
* Current page from the parent. Controls which step circle is highlighted.
|
|
31
|
+
* Non-workflow pages (e.g. data_preview) use index 0 as a valid CDK fallback;
|
|
32
|
+
* the no-active-step CSS class removes the visual active indicator for those pages.
|
|
33
|
+
*/
|
|
34
|
+
readonly currentPage: import("@angular/core").InputSignal<PageId>;
|
|
35
|
+
/**
|
|
36
|
+
* Navigation callback provided by App.
|
|
37
|
+
* Using a callback (instead of an output EventEmitter) matches the existing
|
|
38
|
+
* header-bar pattern and ensures the custom-element page-attribute is reflected.
|
|
39
|
+
*/
|
|
40
|
+
readonly onNavigate: import("@angular/core").InputSignal<(page: PageId) => void>;
|
|
41
|
+
private readonly validationSvc;
|
|
42
|
+
private readonly workflowPage;
|
|
43
|
+
protected readonly pagesWithErrors: import("@angular/core").Signal<Set<PageId>>;
|
|
44
|
+
protected readonly isOnWorkflowPage: import("@angular/core").Signal<boolean>;
|
|
45
|
+
protected readonly clampedStepIndex: import("@angular/core").Signal<number>;
|
|
46
|
+
protected onSelectedIndexChange(index: number): void;
|
|
47
|
+
protected onStepperClick(event: MouseEvent): void;
|
|
48
|
+
private navigateTo;
|
|
49
|
+
}
|
|
@@ -29,10 +29,8 @@ export declare class NaebiDataService {
|
|
|
29
29
|
hoursPerDay: number;
|
|
30
30
|
};
|
|
31
31
|
stall: {
|
|
32
|
-
stableSystem:
|
|
33
|
-
stableCapacity: number;
|
|
32
|
+
stableSystem: string;
|
|
34
33
|
stableVentilationType: number;
|
|
35
|
-
stableAirPurification: number;
|
|
36
34
|
hasStableDeepLitter: boolean;
|
|
37
35
|
hasStableManureBeltDrying: boolean;
|
|
38
36
|
stableManureRemovalFrequency: number;
|
|
@@ -41,10 +39,6 @@ export declare class NaebiDataService {
|
|
|
41
39
|
hasStableFeedingStationElevated: boolean;
|
|
42
40
|
hasStableFloorSlopedUrineDrainage: boolean;
|
|
43
41
|
hasYard: boolean;
|
|
44
|
-
yardFeeding: number;
|
|
45
|
-
yardFloorType: number;
|
|
46
|
-
yardDays: number;
|
|
47
|
-
yardHoursPerDay: number;
|
|
48
42
|
};
|
|
49
43
|
};
|
|
50
44
|
hasImpexDerivedExcretion: boolean;
|
|
@@ -52,6 +46,7 @@ export declare class NaebiDataService {
|
|
|
52
46
|
feeding: {
|
|
53
47
|
fodderConsumption: number;
|
|
54
48
|
concentratedFeedstuffConsumption: number;
|
|
49
|
+
concentratedFeedStuffConsumption: number;
|
|
55
50
|
winterFeeding: {
|
|
56
51
|
feedingRoutine: {
|
|
57
52
|
typeOfFeedstuffProduct: string;
|
|
@@ -76,19 +71,14 @@ export declare class NaebiDataService {
|
|
|
76
71
|
}[];
|
|
77
72
|
storage: {
|
|
78
73
|
stableStrawLitter: number;
|
|
79
|
-
manureSupplyProportionStored: number;
|
|
80
74
|
slurrySupplyProportionStored: number;
|
|
81
75
|
createFacilitySpecificManureProduct: boolean;
|
|
82
76
|
createFacilitySpecificSlurryProduct: boolean;
|
|
77
|
+
slurryTankQuantity: number;
|
|
83
78
|
dilutionRatio: number;
|
|
84
|
-
manurePit:
|
|
85
|
-
cover: number;
|
|
86
|
-
manureFromAnimalStockStored: {
|
|
87
|
-
manureDerivation: string;
|
|
88
|
-
proportionStored: number;
|
|
89
|
-
}[];
|
|
90
|
-
}[];
|
|
79
|
+
manurePit: never[];
|
|
91
80
|
slurryTank: {
|
|
81
|
+
descriptor: string;
|
|
92
82
|
volumeInM3: number;
|
|
93
83
|
depthInM: number;
|
|
94
84
|
cover: number;
|
|
@@ -97,16 +87,7 @@ export declare class NaebiDataService {
|
|
|
97
87
|
}[];
|
|
98
88
|
};
|
|
99
89
|
farmManureTrading: {
|
|
100
|
-
supply:
|
|
101
|
-
quantity: number;
|
|
102
|
-
typeOfManureRecyclingProduct: string;
|
|
103
|
-
transactionUnit: string;
|
|
104
|
-
ingredient: {
|
|
105
|
-
quantity: number;
|
|
106
|
-
molecularFormula: string;
|
|
107
|
-
unit: string;
|
|
108
|
-
}[];
|
|
109
|
-
}[];
|
|
90
|
+
supply: never[];
|
|
110
91
|
dispense: {
|
|
111
92
|
quantity: number;
|
|
112
93
|
typeOfManureRecyclingProduct: string;
|
|
@@ -115,6 +96,11 @@ export declare class NaebiDataService {
|
|
|
115
96
|
zoologicalAnimal: string;
|
|
116
97
|
percentageAllocation: number;
|
|
117
98
|
}[];
|
|
99
|
+
ingredient: {
|
|
100
|
+
quantity: number;
|
|
101
|
+
molecularFormula: string;
|
|
102
|
+
unit: string;
|
|
103
|
+
}[];
|
|
118
104
|
}[];
|
|
119
105
|
};
|
|
120
106
|
fieldSpreading: {
|
|
@@ -138,6 +124,7 @@ export declare class NaebiDataService {
|
|
|
138
124
|
proportionAppliedOtherMonths: number;
|
|
139
125
|
};
|
|
140
126
|
fertiliser: {
|
|
127
|
+
descriptor: string;
|
|
141
128
|
fertiliserProductCategory: string;
|
|
142
129
|
quantity: number;
|
|
143
130
|
transactionUnit: string;
|
|
@@ -159,8 +146,6 @@ export declare class NaebiDataService {
|
|
|
159
146
|
}[];
|
|
160
147
|
};
|
|
161
148
|
lifetimePerformance: {
|
|
162
|
-
dailyGain: number;
|
|
163
|
-
liveWeight: number;
|
|
164
149
|
milkProductionReport: number;
|
|
165
150
|
};
|
|
166
151
|
fodder: {
|
|
@@ -175,6 +160,12 @@ export declare class NaebiDataService {
|
|
|
175
160
|
unit: string;
|
|
176
161
|
}[];
|
|
177
162
|
}[];
|
|
163
|
+
dispense: {
|
|
164
|
+
typeOfFeedstuffProduct: string;
|
|
165
|
+
quantity: number;
|
|
166
|
+
transactionUnit: string;
|
|
167
|
+
ingredient: never[];
|
|
168
|
+
}[];
|
|
178
169
|
};
|
|
179
170
|
cropFromNonFodderCropland: {
|
|
180
171
|
typeOfFeedstuffProduct: string;
|
|
@@ -190,6 +181,17 @@ export declare class NaebiDataService {
|
|
|
190
181
|
totalBalanceErrorMargin: number;
|
|
191
182
|
};
|
|
192
183
|
fieldCultivation: {
|
|
184
|
+
buildingZoneAreaSize: number;
|
|
185
|
+
outdoorVegetableMainCropAreaSize: number;
|
|
186
|
+
indoorVegetableMainCropAreaSize: number;
|
|
187
|
+
feedingOfCropHarvest: {
|
|
188
|
+
agronomicCropCategory: string;
|
|
189
|
+
effectiveYield: number;
|
|
190
|
+
}[];
|
|
191
|
+
dispenseOfCropHarvest: {
|
|
192
|
+
agronomicCropCategory: string;
|
|
193
|
+
effectiveYield: number;
|
|
194
|
+
}[];
|
|
193
195
|
fodderCropland: ({
|
|
194
196
|
agronomicCropCategory: string;
|
|
195
197
|
isMainCrop: boolean;
|
|
@@ -208,17 +210,25 @@ export declare class NaebiDataService {
|
|
|
208
210
|
isMainCrop: boolean;
|
|
209
211
|
areaSize: number;
|
|
210
212
|
yieldPerSquareMeasure: number;
|
|
213
|
+
hasLongTermYieldDivergence: boolean;
|
|
211
214
|
}[];
|
|
212
215
|
special: {
|
|
213
216
|
agronomicCropCategory: string;
|
|
214
217
|
userSpecificPlantName: string;
|
|
215
218
|
isMainCrop: boolean;
|
|
216
219
|
areaSize: number;
|
|
217
|
-
|
|
220
|
+
requirementCorrection: {
|
|
221
|
+
quantity: number;
|
|
222
|
+
molecularFormula: string;
|
|
223
|
+
unit: string;
|
|
224
|
+
}[];
|
|
218
225
|
}[];
|
|
219
226
|
};
|
|
220
227
|
generateReport: boolean;
|
|
221
228
|
};
|
|
229
|
+
calculationVersion: {
|
|
230
|
+
version: string;
|
|
231
|
+
};
|
|
222
232
|
}>;
|
|
223
233
|
private readonly _lastEmitted;
|
|
224
234
|
private readonly _dirty;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { ErrorHandler
|
|
1
|
+
import { ErrorHandler } from '@angular/core';
|
|
2
2
|
export declare class GlobalErrorHandler implements ErrorHandler {
|
|
3
|
-
private injector;
|
|
4
|
-
constructor(injector: Injector);
|
|
3
|
+
private readonly injector;
|
|
5
4
|
handleError(error: any): void;
|
|
6
5
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PipeTransform, Signal } from '@angular/core';
|
|
2
|
-
export type Locale = 'en' | 'de';
|
|
2
|
+
export type Locale = 'en' | 'de' | 'fr' | 'it';
|
|
3
3
|
export type JsonFormsTranslator = (key: string, defaultMessage: string | undefined, context: unknown) => string;
|
|
4
4
|
export declare class I18nService {
|
|
5
5
|
private readonly _locale;
|
|
@@ -8,13 +8,15 @@ export declare class I18nService {
|
|
|
8
8
|
readonly jsonFormsI18n: Signal<{
|
|
9
9
|
locale: Locale;
|
|
10
10
|
translate: JsonFormsTranslator;
|
|
11
|
+
translateError: (error: unknown, translate: JsonFormsTranslator) => string;
|
|
11
12
|
}>;
|
|
12
13
|
setLocale(locale: Locale): void;
|
|
14
|
+
/** Returns true if the given string is a supported locale key. */
|
|
15
|
+
isValidLocale(value: string): value is Locale;
|
|
13
16
|
t(key: string, defaultMessage?: string): string;
|
|
14
17
|
}
|
|
15
18
|
export declare class TranslatePipe implements PipeTransform {
|
|
16
|
-
private readonly i18n;
|
|
17
19
|
private readonly cache;
|
|
18
|
-
|
|
20
|
+
private readonly i18n;
|
|
19
21
|
transform(key: string, defaultMessage?: string): Signal<string>;
|
|
20
22
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { Locale } from '../i18n/i18n.service';
|
|
2
|
-
|
|
2
|
+
/** The property name of the primary key in a master-data catalog entry. */
|
|
3
|
+
type MasterDataKeyField = string;
|
|
3
4
|
interface MasterDataCatalog {
|
|
4
5
|
entries: any[];
|
|
6
|
+
/** Property name to use as the lookup key; 'id' entries are coerced to Number. */
|
|
5
7
|
key: MasterDataKeyField;
|
|
6
8
|
}
|
|
7
9
|
declare const MASTER_DATA: Record<string, MasterDataCatalog>;
|
|
@@ -21,5 +23,10 @@ export declare class MasterDataService {
|
|
|
21
23
|
resolveUtilisation(id: number | string | null | undefined, locale?: Locale): string;
|
|
22
24
|
resolveManureProduct(code: string | null | undefined, locale?: Locale): string;
|
|
23
25
|
resolveZoologicalAnimal(code: string | null | undefined, locale?: Locale): string;
|
|
26
|
+
resolveCultivationCategory(code: string | null | undefined, locale?: Locale): string;
|
|
27
|
+
resolveAgronomicCropCategory(code: string | null | undefined, locale?: Locale): string;
|
|
28
|
+
resolveFeedstuffProduct(code: string | null | undefined, locale?: Locale): string;
|
|
29
|
+
resolveCover(id: number | string | null | undefined, locale?: Locale): string;
|
|
30
|
+
resolveMixingFrequency(id: number | string | null | undefined, locale?: Locale): string;
|
|
24
31
|
}
|
|
25
32
|
export {};
|
|
@@ -1,8 +1,18 @@
|
|
|
1
|
-
export type SuibiVersion = '
|
|
1
|
+
export type SuibiVersion = 'v2.0';
|
|
2
2
|
export type SubmissionStatus = 'draft' | 'submitted' | 'final';
|
|
3
|
+
/** Which computation modules are active for this dossier. */
|
|
4
|
+
export interface ComputationModules {
|
|
5
|
+
suisseBilanz: boolean;
|
|
6
|
+
gmf: boolean;
|
|
7
|
+
nh3: boolean;
|
|
8
|
+
impex: boolean;
|
|
9
|
+
linear: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare const DEFAULT_COMPUTATION_MODULES: ComputationModules;
|
|
3
12
|
export interface SuibiMetadata {
|
|
4
13
|
title: string;
|
|
5
14
|
suibiVersion: SuibiVersion;
|
|
6
15
|
status: SubmissionStatus;
|
|
16
|
+
modules: ComputationModules;
|
|
7
17
|
}
|
|
8
18
|
export declare const DEFAULT_SUIBI_METADATA: SuibiMetadata;
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
export type PageId = 'welcome' | 'animal_stock' | 'data_preview' | 'storage' | 'field_spreading' | 'farm_manure_trading';
|
|
1
|
+
export type PageId = 'welcome' | 'animal_stock' | 'data_preview' | 'storage' | 'field_spreading' | 'farm_manure_trading' | 'fodder' | 'field_cultivation' | 'validation' | 'results';
|
|
2
2
|
export type AnimalStockCategory = 'base' | 'formOfDetention' | 'feeding';
|
|
3
3
|
export type FarmManureTradingMode = 'supply' | 'dispense';
|
|
4
4
|
export type FarmManureTradingCategory = 'general' | 'derivation' | 'ingredients';
|
|
5
|
+
export type FodderMode = 'supply' | 'dispense' | 'non_fodder_cropland';
|
|
6
|
+
export type FodderCategory = 'general' | 'ingredients';
|
|
5
7
|
export type FieldSpreadingCategory = 'general' | 'fertiliser' | 'recycling';
|
|
8
|
+
export type FieldCultivationTab = 'general' | 'fodderCropland' | 'arableLand' | 'special';
|
|
9
|
+
export type StorageTab = 'manure' | 'slurry';
|
|
10
|
+
export type StorageEntryType = 'manure_pit' | 'slurry_tank';
|
|
6
11
|
/**
|
|
7
12
|
* NavigationService
|
|
8
13
|
* Global reactive store for application routing and deep-link state.
|
|
@@ -38,6 +43,21 @@ export declare class NavigationService {
|
|
|
38
43
|
mode: FarmManureTradingMode;
|
|
39
44
|
index: number;
|
|
40
45
|
} | null>;
|
|
46
|
+
/** Selected fodder detail context (mode + index) */
|
|
47
|
+
readonly selectedFodderDetail: import("@angular/core").WritableSignal<{
|
|
48
|
+
mode: FodderMode;
|
|
49
|
+
index: number;
|
|
50
|
+
} | null>;
|
|
51
|
+
/** Selected field cultivation detail context (tab + index) */
|
|
52
|
+
readonly selectedFieldCultivationDetail: import("@angular/core").WritableSignal<{
|
|
53
|
+
tab: Exclude<FieldCultivationTab, "general">;
|
|
54
|
+
index: number;
|
|
55
|
+
} | null>;
|
|
56
|
+
/** Selected storage detail context (type + index) */
|
|
57
|
+
readonly selectedStorageDetail: import("@angular/core").WritableSignal<{
|
|
58
|
+
type: StorageEntryType;
|
|
59
|
+
index: number;
|
|
60
|
+
} | null>;
|
|
41
61
|
/** True if currently viewing animal stock detail (not list) */
|
|
42
62
|
readonly isAnimalStockDetailView: import("@angular/core").Signal<boolean>;
|
|
43
63
|
/** True if currently on animal stock page (list or detail) */
|
|
@@ -58,10 +78,18 @@ export declare class NavigationService {
|
|
|
58
78
|
navigateToAnimalStockDetail(index: number, category?: AnimalStockCategory): void;
|
|
59
79
|
navigateToFarmManureTradingDetail(mode: FarmManureTradingMode, index: number, category?: FarmManureTradingCategory): void;
|
|
60
80
|
navigateToFarmManureTradingList(): void;
|
|
81
|
+
navigateToFodderDetail(mode: FodderMode, index: number, category?: FodderCategory): void;
|
|
82
|
+
navigateToFodderList(): void;
|
|
61
83
|
navigateToFieldSpreading(category?: FieldSpreadingCategory): void;
|
|
84
|
+
navigateToFieldCultivationDetail(tab: Exclude<FieldCultivationTab, 'general'>, index: number): void;
|
|
85
|
+
navigateToFieldCultivationList(tab?: FieldCultivationTab): void;
|
|
86
|
+
navigateToStorageDetail(type: StorageEntryType, index: number): void;
|
|
87
|
+
navigateToStorageList(tab?: StorageTab): void;
|
|
62
88
|
/**
|
|
63
89
|
* Set active category/tab for current page (without changing page/entry).
|
|
64
90
|
* Generic method supporting any page's categorization navigation.
|
|
91
|
+
* No-op when page and category are already the same values to prevent
|
|
92
|
+
* unnecessary signal emissions that re-trigger the tab index computed.
|
|
65
93
|
*/
|
|
66
94
|
setCategory(page: PageId, category: string): void;
|
|
67
95
|
/**
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { NaebiData } from '../data/naebi-data.service';
|
|
2
|
+
import type { PlanningBalanceResponse } from './planning-balance.types';
|
|
3
|
+
export type { PlanningBalanceResponse } from './planning-balance.types';
|
|
4
|
+
/** Which backend to target for planning requests. */
|
|
5
|
+
export type PlanningEndpoint = 'ebilanz' | 'blw';
|
|
6
|
+
/**
|
|
7
|
+
* Sends NAEBI data to a planning endpoint and exposes the result as a
|
|
8
|
+
* signal-based resource. Call `runPlanning(data, endpoint)` to trigger a request.
|
|
9
|
+
*
|
|
10
|
+
* The ID counter ensures each call re-fetches even if the payload hasn't changed.
|
|
11
|
+
*/
|
|
12
|
+
export declare class PlanningBalanceService {
|
|
13
|
+
private readonly http;
|
|
14
|
+
private readonly metadataSvc;
|
|
15
|
+
private readonly _value;
|
|
16
|
+
private readonly _error;
|
|
17
|
+
private readonly _isLoading;
|
|
18
|
+
private readonly _selectedEndpoint;
|
|
19
|
+
private readonly _lastStartedRequestId;
|
|
20
|
+
private readonly _lastCompletedRequestId;
|
|
21
|
+
private readonly _lastSuccessfulRequestId;
|
|
22
|
+
private _nextId;
|
|
23
|
+
private activeRequestId;
|
|
24
|
+
private activeRequestSub;
|
|
25
|
+
readonly planningResource: {
|
|
26
|
+
value: import("@angular/core").Signal<PlanningBalanceResponse | undefined>;
|
|
27
|
+
error: import("@angular/core").Signal<unknown>;
|
|
28
|
+
isLoading: import("@angular/core").Signal<boolean>;
|
|
29
|
+
hasValue: import("@angular/core").Signal<boolean>;
|
|
30
|
+
lastStartedRequestId: import("@angular/core").Signal<number>;
|
|
31
|
+
lastCompletedRequestId: import("@angular/core").Signal<number>;
|
|
32
|
+
lastSuccessfulRequestId: import("@angular/core").Signal<number>;
|
|
33
|
+
};
|
|
34
|
+
readonly selectedEndpoint: import("@angular/core").Signal<PlanningEndpoint>;
|
|
35
|
+
setSelectedEndpoint(endpoint: PlanningEndpoint): void;
|
|
36
|
+
/** Fire a new planning-balance request with the current NAEBI data payload. */
|
|
37
|
+
runPlanning(data: NaebiData, endpoint?: PlanningEndpoint): void;
|
|
38
|
+
}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript interfaces for the planning-balance API response.
|
|
3
|
+
* These match the eBilanz / BLW response shape observed in the example data.
|
|
4
|
+
*/
|
|
5
|
+
/** A single nutrient quantity entry (kg or % unit). */
|
|
6
|
+
export interface NutrientEntry {
|
|
7
|
+
molecularFormula: string;
|
|
8
|
+
quantity: number;
|
|
9
|
+
quantityCorrected?: number;
|
|
10
|
+
unit: string;
|
|
11
|
+
productFamilyType?: string;
|
|
12
|
+
typeOfManureRecyclingProduct?: string;
|
|
13
|
+
fertiliserProductCategory?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface CalculationVersion {
|
|
16
|
+
version: string;
|
|
17
|
+
validFrom: string;
|
|
18
|
+
validTo: string;
|
|
19
|
+
}
|
|
20
|
+
export interface AreaAndYieldPerAgronomicCropCategory {
|
|
21
|
+
agronomicCropCategory: string;
|
|
22
|
+
areaSize: number;
|
|
23
|
+
effectiveYield: number;
|
|
24
|
+
isMainCrop: boolean;
|
|
25
|
+
isNutrientPoorFodder: boolean;
|
|
26
|
+
yieldPerSquareMeasure?: number;
|
|
27
|
+
}
|
|
28
|
+
export interface AreaPerCultivationType {
|
|
29
|
+
areaSize: number;
|
|
30
|
+
isMainCrop: boolean;
|
|
31
|
+
}
|
|
32
|
+
export interface AreaAndYieldPerCultivationCategory {
|
|
33
|
+
cultivationCategory: string;
|
|
34
|
+
areaAndYieldPerAgronomicCropCategory: AreaAndYieldPerAgronomicCropCategory[];
|
|
35
|
+
areaPerCultivationType: AreaPerCultivationType[];
|
|
36
|
+
}
|
|
37
|
+
export interface AreaPerSubCategory {
|
|
38
|
+
cultivationSubCategory: string;
|
|
39
|
+
areaSize: number;
|
|
40
|
+
isMainCrop: boolean;
|
|
41
|
+
}
|
|
42
|
+
export interface FieldCultivation {
|
|
43
|
+
areaAndYieldPerCultivationCategory: AreaAndYieldPerCultivationCategory[];
|
|
44
|
+
areaPerSubCategory: AreaPerSubCategory[];
|
|
45
|
+
fertilizableAreaSize: number;
|
|
46
|
+
slurrySpreadingAreaSize: number;
|
|
47
|
+
totalAgriculturalLandAreaSize: number;
|
|
48
|
+
}
|
|
49
|
+
export interface FodderQuantity {
|
|
50
|
+
quantity: number;
|
|
51
|
+
unit: string;
|
|
52
|
+
proportionNutrientPoorFodder?: number;
|
|
53
|
+
}
|
|
54
|
+
export interface FodderProduct {
|
|
55
|
+
typeOfFeedstuffProduct: string;
|
|
56
|
+
quantity: number;
|
|
57
|
+
unit: string;
|
|
58
|
+
isNutrientPoorFodder: boolean;
|
|
59
|
+
}
|
|
60
|
+
export interface ConsumptionAnimalStock {
|
|
61
|
+
animalCategoryPRIF: number;
|
|
62
|
+
averageQuantity: number;
|
|
63
|
+
order: string;
|
|
64
|
+
quantity: number;
|
|
65
|
+
unit: string;
|
|
66
|
+
}
|
|
67
|
+
export interface RequiredEffectiveYieldFromFodderCropland {
|
|
68
|
+
consumptionAnimalStock: ConsumptionAnimalStock[];
|
|
69
|
+
cropFromNonFodderCroplandPerProduct: FodderProduct[];
|
|
70
|
+
dispensePerProduct: FodderProduct[];
|
|
71
|
+
supplyPerProduct: FodderProduct[];
|
|
72
|
+
totalBalance: FodderQuantity;
|
|
73
|
+
totalConsumptionAnimalStock: FodderQuantity;
|
|
74
|
+
totalCropFromNonFodderCropland: FodderQuantity;
|
|
75
|
+
totalDispense: FodderQuantity;
|
|
76
|
+
totalSupply: FodderQuantity;
|
|
77
|
+
}
|
|
78
|
+
export interface FodderBalance {
|
|
79
|
+
requiredEffectiveYieldFromFodderCropland: RequiredEffectiveYieldFromFodderCropland;
|
|
80
|
+
totalBalance: FodderQuantity;
|
|
81
|
+
totalEffectiveYieldFromFodderCropland: FodderQuantity;
|
|
82
|
+
totalNutrientPoorFodder: FodderQuantity;
|
|
83
|
+
}
|
|
84
|
+
export interface EmissionAndAccumulationEntry {
|
|
85
|
+
animalCategoryPRIF: number;
|
|
86
|
+
order: string;
|
|
87
|
+
accumulation: NutrientEntry[];
|
|
88
|
+
emission: NutrientEntry[];
|
|
89
|
+
manureExcretion?: unknown[];
|
|
90
|
+
}
|
|
91
|
+
export interface AccumulationEntireExcretion {
|
|
92
|
+
animalCategoryPRIF: number;
|
|
93
|
+
order: string;
|
|
94
|
+
durationSumTotalCorrectedNutrientBalance: number;
|
|
95
|
+
accumulation: NutrientEntry[];
|
|
96
|
+
}
|
|
97
|
+
export interface TotalNutrientSet {
|
|
98
|
+
accumulation: NutrientEntry[];
|
|
99
|
+
emission?: NutrientEntry[];
|
|
100
|
+
}
|
|
101
|
+
export interface AnimalStock {
|
|
102
|
+
accumulationEntireExcretion: AccumulationEntireExcretion[];
|
|
103
|
+
emissionAndAccumulationPasture: EmissionAndAccumulationEntry[];
|
|
104
|
+
emissionAndAccumulationStall: EmissionAndAccumulationEntry[];
|
|
105
|
+
emissionAndAccumulationYard: EmissionAndAccumulationEntry[];
|
|
106
|
+
totalAccumulationEntireExcretion: TotalNutrientSet;
|
|
107
|
+
totalEmissionAndAccumulationAnimalStock: TotalNutrientSet;
|
|
108
|
+
totalEmissionAndAccumulationPasture: TotalNutrientSet;
|
|
109
|
+
totalEmissionAndAccumulationStall: TotalNutrientSet;
|
|
110
|
+
totalEmissionAndAccumulationYard: TotalNutrientSet;
|
|
111
|
+
}
|
|
112
|
+
export interface ManureTradingProduct {
|
|
113
|
+
typeOfManureRecyclingProduct: string;
|
|
114
|
+
quantity: number;
|
|
115
|
+
unit: string;
|
|
116
|
+
ingredient: NutrientEntry[];
|
|
117
|
+
}
|
|
118
|
+
export interface FarmManureTrading {
|
|
119
|
+
balancePerProduct: ManureTradingProduct[];
|
|
120
|
+
dispensePerProduct: ManureTradingProduct[];
|
|
121
|
+
supplyPerProduct: ManureTradingProduct[];
|
|
122
|
+
totalBalance: {
|
|
123
|
+
ingredient: NutrientEntry[];
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
export interface NutrientRequirementEntry {
|
|
127
|
+
agronomicCropCategory?: string;
|
|
128
|
+
cultivationCategory?: string;
|
|
129
|
+
isMainCrop?: boolean;
|
|
130
|
+
requirement: NutrientEntry[];
|
|
131
|
+
}
|
|
132
|
+
export interface FieldCultivationNutrients {
|
|
133
|
+
nutrientTransferUnfertilizedCultivation: NutrientEntry[];
|
|
134
|
+
requirementPerAgronomicCropCategory: NutrientRequirementEntry[];
|
|
135
|
+
requirementPerCultivationCategory: NutrientRequirementEntry[];
|
|
136
|
+
totalRequirement: NutrientEntry[];
|
|
137
|
+
}
|
|
138
|
+
export interface FieldSpreading {
|
|
139
|
+
emissionAndAccumulationFieldSpreading: TotalNutrientSet;
|
|
140
|
+
totalEmissionAndAccumulationFieldSpreading: TotalNutrientSet;
|
|
141
|
+
}
|
|
142
|
+
export interface StorageBalance {
|
|
143
|
+
emissionAndAccumulationManureStorage: TotalNutrientSet;
|
|
144
|
+
totalEmissionAndAccumulationManureStorage: TotalNutrientSet;
|
|
145
|
+
}
|
|
146
|
+
export interface NutrientBalance {
|
|
147
|
+
animalStock: AnimalStock;
|
|
148
|
+
farmManureTrading: FarmManureTrading;
|
|
149
|
+
fieldCultivation: FieldCultivationNutrients;
|
|
150
|
+
fieldSpreading: FieldSpreading;
|
|
151
|
+
storage: StorageBalance;
|
|
152
|
+
/** Final per-nutrient balance figures: kg lines + % lines interleaved. */
|
|
153
|
+
totalBalance: NutrientEntry[];
|
|
154
|
+
/** Farm-wide gas emissions (NH3, NO, N2O, N2). */
|
|
155
|
+
totalEmissionFarm: NutrientEntry[];
|
|
156
|
+
nutrientBalanceTMP?: unknown[];
|
|
157
|
+
}
|
|
158
|
+
export interface NutrientCycle {
|
|
159
|
+
creationDateTime: string;
|
|
160
|
+
facilitySpecificProducts: {
|
|
161
|
+
manureRecyclingProduct: unknown[];
|
|
162
|
+
};
|
|
163
|
+
fieldCultivation: FieldCultivation;
|
|
164
|
+
fodderBalance: FodderBalance;
|
|
165
|
+
nutrientBalance: NutrientBalance;
|
|
166
|
+
version: string;
|
|
167
|
+
/** Base64-encoded PDF report, if returned by the endpoint. */
|
|
168
|
+
report?: string;
|
|
169
|
+
}
|
|
170
|
+
export interface ValidationMessageDetail {
|
|
171
|
+
designation_deu: string;
|
|
172
|
+
designation_eng: string;
|
|
173
|
+
designation_fra: string;
|
|
174
|
+
designation_ita: string;
|
|
175
|
+
}
|
|
176
|
+
export interface ValidationMessage {
|
|
177
|
+
field: string;
|
|
178
|
+
type: string;
|
|
179
|
+
detail: ValidationMessageDetail;
|
|
180
|
+
}
|
|
181
|
+
/** Full response from the planning-balance endpoint. */
|
|
182
|
+
export interface PlanningBalanceResponse {
|
|
183
|
+
calculationVersion: CalculationVersion;
|
|
184
|
+
nutrientCycle: NutrientCycle;
|
|
185
|
+
validationMessage: ValidationMessage[];
|
|
186
|
+
}
|
|
187
|
+
/** Merged kg + % row for the final balance table (Section D). */
|
|
188
|
+
export interface BalanceRow {
|
|
189
|
+
molecularFormula: string;
|
|
190
|
+
quantity: number;
|
|
191
|
+
quantityCorrected: number;
|
|
192
|
+
quantityPct: number | null;
|
|
193
|
+
quantityCorrectedPct: number | null;
|
|
194
|
+
unit: 'kg';
|
|
195
|
+
}
|
|
196
|
+
/** Crop requirement row enriched with area and yield for display (Section C). */
|
|
197
|
+
export interface CropRequirementRow {
|
|
198
|
+
cropCode: string;
|
|
199
|
+
cultivationCategory: string;
|
|
200
|
+
isMainCrop: boolean;
|
|
201
|
+
areaHa: number;
|
|
202
|
+
effectiveYield: number;
|
|
203
|
+
/** kg/ha yield per square measure field (m² basis), converted to dt/ha for display. */
|
|
204
|
+
yieldDtHa: number | null;
|
|
205
|
+
requirement: NutrientEntry[];
|
|
206
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { BalanceRow, NutrientEntry } from './planning-balance.types';
|
|
2
|
+
/**
|
|
3
|
+
* Merges the interleaved kg / % rows from `totalBalance` into one `BalanceRow`
|
|
4
|
+
* per nutrient formula, preserving the canonical KEY_NUTRIENTS display order.
|
|
5
|
+
*
|
|
6
|
+
* The planning-balance API returns two `NutrientEntry` objects per formula
|
|
7
|
+
* (one with `unit === 'kg'`, one with `unit === '%'`). This function coalesces
|
|
8
|
+
* them so callers work with a single, normalised row.
|
|
9
|
+
*/
|
|
10
|
+
export declare function mergeBalanceRows(totalBalance: NutrientEntry[]): BalanceRow[];
|