@agridea/suibi-module 0.1.0-preview.01100f9

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.
Files changed (132) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +120 -0
  3. package/dist/elements/browser/main.js +78 -0
  4. package/dist/elements/browser/polyfills.js +1 -0
  5. package/dist/elements/browser/styles.css +1 -0
  6. package/dist/elements/browser/suibi-module-latest.css +1 -0
  7. package/dist/elements/browser/suibi-module-latest.js +78 -0
  8. package/dist/elements/browser/suibi-module.v0.1.0-preview.01100f9.css +1 -0
  9. package/dist/elements/browser/suibi-module.v0.1.0-preview.01100f9.js +78 -0
  10. package/dist/elements/browser/suibi-theme-dark.css +1 -0
  11. package/dist/elements/browser/version.txt +1 -0
  12. package/dist/elements/browser/wc-global-utilities.css +1 -0
  13. package/dist/types/app/app.config.d.ts +2 -0
  14. package/dist/types/app/app.d.ts +34 -0
  15. package/dist/types/app/components/add-dashed-button/add-dashed-button.component.d.ts +9 -0
  16. package/dist/types/app/components/data-preview/data-preview.component.d.ts +11 -0
  17. package/dist/types/app/components/empty-state/empty-state.component.d.ts +12 -0
  18. package/dist/types/app/components/gauge-arc/gauge-arc.component.d.ts +49 -0
  19. package/dist/types/app/components/header-bar/header-bar.component.d.ts +14 -0
  20. package/dist/types/app/components/inline-table/inline-table.component.d.ts +137 -0
  21. package/dist/types/app/components/inline-table/inline-table.types.d.ts +203 -0
  22. package/dist/types/app/components/module-placeholder-page/module-placeholder-page.component.d.ts +6 -0
  23. package/dist/types/app/components/planning-result/planning-result.component.d.ts +46 -0
  24. package/dist/types/app/components/planning-result-row/planning-result-row.component.d.ts +34 -0
  25. package/dist/types/app/components/planning-trigger/planning-trigger.component.d.ts +13 -0
  26. package/dist/types/app/components/results-page/results-page.component.d.ts +13 -0
  27. package/dist/types/app/components/suissebilanz-dashboard/suissebilanz-dashboard.component.d.ts +32 -0
  28. package/dist/types/app/components/suissebilanz-dashboard/suissebilanz-metrics.service.d.ts +21 -0
  29. package/dist/types/app/components/suissebilanz-minibar/suissebilanz-minibar.component.d.ts +19 -0
  30. package/dist/types/app/components/validation-errors-panel/validation-errors-panel.component.d.ts +36 -0
  31. package/dist/types/app/components/validation-page/validation-page.component.d.ts +18 -0
  32. package/dist/types/app/components/welcome-page/metadata.types.d.ts +1 -0
  33. package/dist/types/app/components/welcome-page/welcome-page.component.d.ts +30 -0
  34. package/dist/types/app/components/workflow-stepper/workflow-stepper.component.d.ts +49 -0
  35. package/dist/types/app/core/data/naebi-data.service.d.ts +253 -0
  36. package/dist/types/app/core/error/global-error-handler.d.ts +5 -0
  37. package/dist/types/app/core/events/suibi-data-emitter.service.d.ts +13 -0
  38. package/dist/types/app/core/events/suibi-data-event.d.ts +26 -0
  39. package/dist/types/app/core/i18n/i18n.service.d.ts +22 -0
  40. package/dist/types/app/core/i18n/locales/de.d.ts +2 -0
  41. package/dist/types/app/core/i18n/locales/en.d.ts +2 -0
  42. package/dist/types/app/core/i18n/locales/fr.d.ts +2 -0
  43. package/dist/types/app/core/i18n/locales/it.d.ts +2 -0
  44. package/dist/types/app/core/master-data/master-data.service.d.ts +32 -0
  45. package/dist/types/app/core/metadata/suibi-metadata.service.d.ts +6 -0
  46. package/dist/types/app/core/metadata/suibi-metadata.types.d.ts +18 -0
  47. package/dist/types/app/core/navigation/navigation.service.d.ts +100 -0
  48. package/dist/types/app/core/planning/planning-balance.service.d.ts +38 -0
  49. package/dist/types/app/core/planning/planning-balance.types.d.ts +206 -0
  50. package/dist/types/app/core/planning/planning-balance.utils.d.ts +10 -0
  51. package/dist/types/app/core/schemas/index.d.ts +18 -0
  52. package/dist/types/app/core/schemas/schema-localization.util.d.ts +18 -0
  53. package/dist/types/app/core/schemas/schema-merge.util.d.ts +26 -0
  54. package/dist/types/app/core/schemas/ui-helper-registry.d.ts +16 -0
  55. package/dist/types/app/core/telemetry/telemetry.service.d.ts +12 -0
  56. package/dist/types/app/core/utils/object.util.d.ts +50 -0
  57. package/dist/types/app/core/validation/ajv-custom.d.ts +15 -0
  58. package/dist/types/app/core/validation/capabilities.d.ts +18 -0
  59. package/dist/types/app/core/validation/error-formatter.d.ts +19 -0
  60. package/dist/types/app/core/validation/global-validation.service.d.ts +59 -0
  61. package/dist/types/app/jsonforms/constraints/constraint-resolvers.d.ts +50 -0
  62. package/dist/types/app/jsonforms/filters/code-list-filter-resolvers.d.ts +63 -0
  63. package/dist/types/app/jsonforms/registry/renderers.registry.d.ts +38 -0
  64. package/dist/types/app/jsonforms/renderers/controls/selects/animal-category/animal-category-select.renderer.d.ts +21 -0
  65. package/dist/types/app/jsonforms/renderers/controls/selects/code-list/code-list-select.renderer.d.ts +34 -0
  66. package/dist/types/app/jsonforms/renderers/layout/array/array-layout.renderer.d.ts +43 -0
  67. package/dist/types/app/jsonforms/renderers/layout/categorization/selected-category-categorization.renderer.d.ts +34 -0
  68. package/dist/types/app/jsonforms/renderers/layout/constraint/constraint-layout.renderer.d.ts +31 -0
  69. package/dist/types/app/jsonforms/renderers/layout/group/base-group.renderer.d.ts +31 -0
  70. package/dist/types/app/jsonforms/renderers/layout/group/card-group.renderer.d.ts +6 -0
  71. package/dist/types/app/jsonforms/renderers/layout/group/group-testers.d.ts +4 -0
  72. package/dist/types/app/jsonforms/renderers/layout/group/logical-group.renderer.d.ts +6 -0
  73. package/dist/types/app/jsonforms/renderers/layout/group/module-toggle-group.renderer.d.ts +38 -0
  74. package/dist/types/app/jsonforms/renderers/layout/group/plain-group.renderer.d.ts +6 -0
  75. package/dist/types/app/jsonforms/shared/base-control/base-select-control.d.ts +16 -0
  76. package/dist/types/app/jsonforms/shared/option-sources/code-lists.d.ts +11 -0
  77. package/dist/types/app/jsonforms/shared/validation/field-error.service.d.ts +18 -0
  78. package/dist/types/app/nutrient-cycle/animal-stock/animal-stock-detail/animal-stock-detail.component.d.ts +21 -0
  79. package/dist/types/app/nutrient-cycle/animal-stock/animal-stock-list/animal-stock-list.component.d.ts +18 -0
  80. package/dist/types/app/nutrient-cycle/animal-stock/animal-stock-master-detail/animal-stock-master-detail.component.d.ts +24 -0
  81. package/dist/types/app/nutrient-cycle/animal-stock/animal-stock.types.d.ts +69 -0
  82. package/dist/types/app/nutrient-cycle/animal-stock/index.d.ts +4 -0
  83. package/dist/types/app/nutrient-cycle/farm-manure-trading/farm-manure-trading-master-detail/farm-manure-trading-master-detail.component.d.ts +19 -0
  84. package/dist/types/app/nutrient-cycle/farm-manure-trading/farm-manure-trading-table/farm-manure-trading-table.component.d.ts +34 -0
  85. package/dist/types/app/nutrient-cycle/farm-manure-trading/farm-manure-trading-table/farm-manure-trading-table.config.d.ts +24 -0
  86. package/dist/types/app/nutrient-cycle/farm-manure-trading/farm-manure-trading.types.d.ts +27 -0
  87. package/dist/types/app/nutrient-cycle/farm-manure-trading/index.d.ts +4 -0
  88. package/dist/types/app/nutrient-cycle/farm-manure-trading/transaction-unit.util.d.ts +3 -0
  89. package/dist/types/app/nutrient-cycle/field-cultivation/arable-land-table/arable-land-table.component.d.ts +21 -0
  90. package/dist/types/app/nutrient-cycle/field-cultivation/arable-land-table/arable-land-table.config.d.ts +9 -0
  91. package/dist/types/app/nutrient-cycle/field-cultivation/crop-harvest-table/crop-harvest-table.component.d.ts +21 -0
  92. package/dist/types/app/nutrient-cycle/field-cultivation/crop-harvest-table/crop-harvest-table.config.d.ts +13 -0
  93. package/dist/types/app/nutrient-cycle/field-cultivation/field-cultivation-detail/field-cultivation-detail.component.d.ts +22 -0
  94. package/dist/types/app/nutrient-cycle/field-cultivation/field-cultivation-general/field-cultivation-general.component.d.ts +20 -0
  95. package/dist/types/app/nutrient-cycle/field-cultivation/field-cultivation-list/field-cultivation-list.component.d.ts +17 -0
  96. package/dist/types/app/nutrient-cycle/field-cultivation/field-cultivation-master-detail/field-cultivation-master-detail.component.d.ts +29 -0
  97. package/dist/types/app/nutrient-cycle/field-cultivation/field-cultivation.types.d.ts +41 -0
  98. package/dist/types/app/nutrient-cycle/field-cultivation/field-cultivation.util.d.ts +6 -0
  99. package/dist/types/app/nutrient-cycle/field-cultivation/fodder-cropland-table/fodder-cropland-table.component.d.ts +27 -0
  100. package/dist/types/app/nutrient-cycle/field-cultivation/fodder-cropland-table/fodder-cropland-table.config.d.ts +16 -0
  101. package/dist/types/app/nutrient-cycle/field-cultivation/index.d.ts +9 -0
  102. package/dist/types/app/nutrient-cycle/field-cultivation/special-crops-table/special-crops-table.component.d.ts +29 -0
  103. package/dist/types/app/nutrient-cycle/field-cultivation/special-crops-table/special-crops-table.config.d.ts +61 -0
  104. package/dist/types/app/nutrient-cycle/field-spreading/fertiliser-table/fertiliser-table.component.d.ts +43 -0
  105. package/dist/types/app/nutrient-cycle/field-spreading/fertiliser-table/fertiliser-table.config.d.ts +20 -0
  106. package/dist/types/app/nutrient-cycle/field-spreading/field-spreading.component.d.ts +34 -0
  107. package/dist/types/app/nutrient-cycle/field-spreading/field-spreading.types.d.ts +43 -0
  108. package/dist/types/app/nutrient-cycle/field-spreading/index.d.ts +2 -0
  109. package/dist/types/app/nutrient-cycle/field-spreading/ingredient.util.d.ts +8 -0
  110. package/dist/types/app/nutrient-cycle/field-spreading/recycling-table/recycling-table.component.d.ts +31 -0
  111. package/dist/types/app/nutrient-cycle/field-spreading/recycling-table/recycling-table.config.d.ts +17 -0
  112. package/dist/types/app/nutrient-cycle/field-spreading/recycling-table/recycling-transaction-unit.util.d.ts +4 -0
  113. package/dist/types/app/nutrient-cycle/fodder/fodder-master-detail/fodder-master-detail.component.d.ts +25 -0
  114. package/dist/types/app/nutrient-cycle/fodder/fodder-table/fodder-table.component.d.ts +26 -0
  115. package/dist/types/app/nutrient-cycle/fodder/fodder-table/fodder-table.config.d.ts +9 -0
  116. package/dist/types/app/nutrient-cycle/fodder/fodder.types.d.ts +34 -0
  117. package/dist/types/app/nutrient-cycle/fodder/index.d.ts +3 -0
  118. package/dist/types/app/nutrient-cycle/fodder/ingredient.util.d.ts +8 -0
  119. package/dist/types/app/nutrient-cycle/fodder/transaction-unit.util.d.ts +2 -0
  120. package/dist/types/app/nutrient-cycle/lifetime-performance/index.d.ts +2 -0
  121. package/dist/types/app/nutrient-cycle/lifetime-performance/lifetime-performance-form.component.d.ts +27 -0
  122. package/dist/types/app/nutrient-cycle/lifetime-performance/lifetime-performance.types.d.ts +5 -0
  123. package/dist/types/app/nutrient-cycle/storage/index.d.ts +4 -0
  124. package/dist/types/app/nutrient-cycle/storage/storage-detail/storage-detail.component.d.ts +30 -0
  125. package/dist/types/app/nutrient-cycle/storage/storage-general/storage-general.component.d.ts +29 -0
  126. package/dist/types/app/nutrient-cycle/storage/storage-list/storage-list.component.d.ts +23 -0
  127. package/dist/types/app/nutrient-cycle/storage/storage-master-detail/storage-master-detail.component.d.ts +32 -0
  128. package/dist/types/app/nutrient-cycle/storage/storage.types.d.ts +40 -0
  129. package/dist/types/environments/environment.d.ts +11 -0
  130. package/dist/types/public-api.d.ts +6 -0
  131. package/dist/types/shared/material-icons.d.ts +16 -0
  132. package/package.json +142 -0
@@ -0,0 +1,100 @@
1
+ export type PageId = 'welcome' | 'animal_stock' | 'data_preview' | 'storage' | 'field_spreading' | 'farm_manure_trading' | 'fodder' | 'field_cultivation' | 'validation' | 'results';
2
+ export type AnimalStockCategory = 'base' | 'formOfDetention' | 'feeding';
3
+ export type FarmManureTradingMode = 'supply' | 'dispense';
4
+ export type FarmManureTradingCategory = 'general' | 'derivation' | 'ingredients';
5
+ export type FodderMode = 'supply' | 'dispense' | 'non_fodder_cropland';
6
+ export type FodderCategory = 'general' | 'ingredients';
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';
11
+ /**
12
+ * NavigationService
13
+ * Global reactive store for application routing and deep-link state.
14
+ * Follows Pinia/Vuex pattern: signals = state, computed = getters, methods = actions.
15
+ *
16
+ * Responsibilities:
17
+ * - Track current page and page-specific context (e.g., selected entity index, active tab)
18
+ * - Provide navigation actions that update state atomically
19
+ * - Used by validation system to deep-link users to fields requiring correction
20
+ *
21
+ * Pattern for adding new pages:
22
+ * 1. Add page ID to PageId type
23
+ * 2. Add page-specific state signals (e.g., selectedStorageIndex)
24
+ * 3. Add navigation actions (e.g., navigateToStorageDetail)
25
+ * 4. Update reset logic in resetPageContext()
26
+ */
27
+ export declare class NavigationService {
28
+ /** Current active page */
29
+ readonly currentPage: import("@angular/core").WritableSignal<PageId>;
30
+ /** Selected animal stock entry index (null = list view) */
31
+ readonly selectedAnimalStockIndex: import("@angular/core").WritableSignal<number | null>;
32
+ /**
33
+ * Generic category (tab) selection: stores current page + selected category key.
34
+ * Used by categorization renderer for programmatic tab control.
35
+ * Format: { page: PageId, category: string }
36
+ */
37
+ readonly selectedCategory: import("@angular/core").WritableSignal<{
38
+ page: PageId;
39
+ category: string;
40
+ }>;
41
+ /** Selected farm manure trading detail context (mode + index) */
42
+ readonly selectedFarmManureTrading: import("@angular/core").WritableSignal<{
43
+ mode: FarmManureTradingMode;
44
+ index: number;
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>;
61
+ /** True if currently viewing animal stock detail (not list) */
62
+ readonly isAnimalStockDetailView: import("@angular/core").Signal<boolean>;
63
+ /** True if currently on animal stock page (list or detail) */
64
+ readonly isAnimalStockPage: import("@angular/core").Signal<boolean>;
65
+ /**
66
+ * Navigate to a top-level page. Resets page-specific context.
67
+ * Use this for simple page switches (e.g., nav menu clicks).
68
+ */
69
+ navigateToPage(page: PageId): void;
70
+ /**
71
+ * Navigate to animal stock list view (no entry selected).
72
+ */
73
+ navigateToAnimalStockList(): void;
74
+ /**
75
+ * Navigate to animal stock detail view (specific entry + optional tab).
76
+ * Used by validation error navigation and internal routing.
77
+ */
78
+ navigateToAnimalStockDetail(index: number, category?: AnimalStockCategory): void;
79
+ navigateToFarmManureTradingDetail(mode: FarmManureTradingMode, index: number, category?: FarmManureTradingCategory): void;
80
+ navigateToFarmManureTradingList(): void;
81
+ navigateToFodderDetail(mode: FodderMode, index: number, category?: FodderCategory): void;
82
+ navigateToFodderList(): void;
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;
88
+ /**
89
+ * Set active category/tab for current page (without changing page/entry).
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.
93
+ */
94
+ setCategory(page: PageId, category: string): void;
95
+ /**
96
+ * Reset page-specific context when navigating away.
97
+ * Prevents stale state (e.g., old selected index) from affecting new page.
98
+ */
99
+ private resetPageContext;
100
+ }
@@ -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[];
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Schema utilities for managing UI-only helper fields in JSONForms components.
3
+ *
4
+ * This module provides centralized schema merging and helper field filtering to maintain
5
+ * clean separation between domain schemas (nutrient balance calculation model) and
6
+ * UI-only helper fields that drive conditional rendering logic.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { mergeSchemas, getUiHelperFields, stripUiHelpers } from '@core/schemas';
11
+ * import globalUiExtensions from '@core/schemas/ui-schema-extensions.json';
12
+ *
13
+ * const helpers = getUiHelperFields(globalUiExtensions);
14
+ * const merged = mergeSchemas(domainSchema, globalUiExtensions);
15
+ * const clean = stripUiHelpers(formData, helpers);
16
+ * ```
17
+ */
18
+ export { mergeSchemas, getUiHelperFields, stripUiHelpers } from './schema-merge.util';
@@ -0,0 +1,18 @@
1
+ import { UISchemaElement } from '@jsonforms/core';
2
+ /**
3
+ * Deeply clones a UI schema and translates its labels.
4
+ *
5
+ * This utility is essential for JSONForms integration in a multi-language environment.
6
+ * Since UI schemas are typically static JSON objects, we must clone them before
7
+ * modifying their labels to avoid mutating the shared source or leaking translations
8
+ * across language switches.
9
+ *
10
+ * It traverses:
11
+ * - Nested `elements` arrays (standard layouts)
12
+ * - `options.detail` objects (often used in array controls)
13
+ *
14
+ * @param ui The original UI schema to localize
15
+ * @param translate A function that takes a translation key and returns the translated string
16
+ * @returns A new UI schema object with translated labels
17
+ */
18
+ export declare function cloneAndLocalize(ui: any, translate: (key: string) => string): UISchemaElement;
@@ -0,0 +1,26 @@
1
+ import { JsonSchema } from '@jsonforms/core';
2
+ /**
3
+ * Merges a base domain schema with UI-only extension properties at runtime.
4
+ * Extensions are deep-cloned into the base schema to avoid mutation.
5
+ *
6
+ * @param base - Domain schema (e.g., nutrient balance data model)
7
+ * @param extensions - UI helper schema with `x-ui-helper: true` fields
8
+ * @returns Merged schema suitable for JSONForms consumption
9
+ */
10
+ export declare function mergeSchemas(base: JsonSchema, extensions: JsonSchema): JsonSchema;
11
+ /**
12
+ * Extracts field names marked as UI helpers from a schema.
13
+ * Scans properties for `"x-ui-helper": true` metadata.
14
+ *
15
+ * @param schema - Schema to scan (typically UI extensions schema)
16
+ * @returns Set of field names that should be filtered from persisted data
17
+ */
18
+ export declare function getUiHelperFields(schema: JsonSchema): Set<string>;
19
+ /**
20
+ * Removes all UI helper fields from a data object.
21
+ * Mutates the input object (use with caution; prefer spreading first).
22
+ *
23
+ * @param data - Data object to clean (typically form state)
24
+ * @param helperFields - Set of field names to remove
25
+ */
26
+ export declare function stripUiHelpers<T extends Record<string, any>>(data: T, helperFields: Set<string>): Omit<T, string>;
@@ -0,0 +1,16 @@
1
+ export interface UiHelperDefinitions {
2
+ durationSourceType?: 'tvd-original' | 'tvd-final' | 'self-reported';
3
+ quantity_correction?: boolean;
4
+ }
5
+ export interface UiHelperConfig<K extends keyof UiHelperDefinitions = keyof UiHelperDefinitions> {
6
+ key: K;
7
+ default: () => UiHelperDefinitions[K] | undefined;
8
+ derive?: (domain: any) => UiHelperDefinitions[K] | undefined;
9
+ readonly?: boolean;
10
+ }
11
+ export declare function getHelperKeys(): (keyof UiHelperDefinitions)[];
12
+ export declare function deriveHelpers(domain: any): Partial<UiHelperDefinitions>;
13
+ export declare function augmentData<T extends object>(domain: T): T & UiHelperDefinitions;
14
+ export declare function stripHelpers<T extends object>(data: T): T;
15
+ export declare function prepareJsonFormsData<T extends object>(domain: T | null | undefined): (T & UiHelperDefinitions) | null;
16
+ export declare function sanitizeJsonFormsData<T extends object>(formData: T): T;
@@ -0,0 +1,12 @@
1
+ export declare class TelemetryService {
2
+ private appInsights;
3
+ private isEnabled;
4
+ constructor();
5
+ private init;
6
+ setTelemetryEnabled(enabled: boolean): void;
7
+ trackPageView(name?: string, uri?: string): void;
8
+ trackEvent(name: string, properties?: {
9
+ [key: string]: any;
10
+ }): void;
11
+ trackException(exception: Error): void;
12
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Recursively compares two values for deep equality.
3
+ *
4
+ * Useful for checking if complex objects or arrays have changed content,
5
+ * often used in change detection strategies or form dirty checking.
6
+ *
7
+ * @param a The first value to compare
8
+ * @param b The second value to compare
9
+ * @returns True if the values are deeply equal, false otherwise
10
+ */
11
+ export declare function deepEqual(a: unknown, b: unknown): boolean;
12
+ /**
13
+ * Creates a deep copy of a value.
14
+ *
15
+ * Essential for immutable state updates where you need to modify a nested property
16
+ * without mutating the original object.
17
+ *
18
+ * Uses `structuredClone` if available, falling back to JSON serialization.
19
+ * Note: The JSON fallback has limitations (e.g. loses Date objects, functions, undefined).
20
+ *
21
+ * @param value The value to clone
22
+ * @returns A deep copy of the value
23
+ */
24
+ export declare function deepClone<T>(value: T): T;
25
+ /**
26
+ * Recursively drops `ingredient[]` entries whose `quantity` is null/undefined.
27
+ *
28
+ * Inline tables (fertiliser/recycling) pre-populate every nutrient slot in `ingredient[]`
29
+ * so the UI always shows all formula columns, but slots the user never fills in stay as
30
+ * `{ molecularFormula, quantity: null, unit }`. The calculation API rejects any ingredient
31
+ * entry that's present but incomplete, so submitted payloads must omit those still-empty
32
+ * slots entirely rather than send them with a null quantity.
33
+ */
34
+ export declare function stripIncompleteIngredients<T>(value: T): T;
35
+ /**
36
+ * Sanitizes the planning payload: the calculation API (OpenAPI, no `nullable: true`
37
+ * anywhere) accepts an optional field as *absent* but rejects it when present with a
38
+ * null value ("must be string/number"). The working data model normalizes optional
39
+ * fields to null, so strip them at the submission boundary — mirroring what
40
+ * `stripIncompleteIngredients` does for ingredient slots.
41
+ *
42
+ * - inside `fieldCultivation` entry collections (fodderCropland, arableLand, special,
43
+ * feedingOfCropHarvest, dispenseOfCropHarvest): any null property is dropped
44
+ * (fieldName, userSpecificPlantName, yieldPerSquareMeasure, effectiveYield, …)
45
+ * - `nutrientCycle.fodder.trading.<collection>[].quantity`: null → dropped
46
+ */
47
+ export declare function sanitizePlanningPayload(data: NaebiDataLike): NaebiDataLike;
48
+ /** Structural type so object.util stays free of a NaebiData import (circular-safe). */
49
+ type NaebiDataLike = Record<string, unknown>;
50
+ export {};
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Custom AJV instance with capability-based validation keywords.
3
+ * Focus: keep declarative business rules in JSON Schema while deriving dynamic
4
+ * constraints from static master data (no runtime HTTP calls).
5
+ */
6
+ import Ajv from 'ajv';
7
+ /**
8
+ * Creates a custom AJV instance with domain-specific validation keywords.
9
+ *
10
+ * Custom keywords:
11
+ * - `permittedStableSystem`: Validates stable system against animal category constraints
12
+ *
13
+ * @param options - Additional AJV options to merge with defaults
14
+ */
15
+ export declare function createSuibiAjv(options?: Record<string, any>): Ajv;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Dynamic capability derivation from master data.
3
+ * Computes permitted stable systems, utilisations, etc. based on animal categories.
4
+ *
5
+ * All master data is embedded statically at compile time - no runtime HTTP calls.
6
+ */
7
+ /**
8
+ * Derives permitted stable systems (stableSystem enum strings) for a given animal category.
9
+ *
10
+ * @param animalCategoryPRIF - The PRIF animal category ID
11
+ * @returns Array of permitted stableSystem enum strings (e.g. 'HUS_TETHER')
12
+ */
13
+ export declare function derivePermittedStableSystems(animalCategoryPRIF: number | null | undefined): string[];
14
+ /**
15
+ * Pre-computed map for performance (memoized at module load).
16
+ * Maps animalCategoryPRIF -> array of permitted stableSystem enum strings.
17
+ */
18
+ export declare const PERMITTED_STABLE_SYSTEMS: Record<number, string[]>;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Error message formatter for JSON Schema validation.
3
+ * Maps AJV error objects to i18n keys with parameters.
4
+ *
5
+ * Since validation is handled by AJV/JSON Schema, we don't need a custom engine.
6
+ * We just need to format error messages for better UX.
7
+ */
8
+ /**
9
+ * Format an AJV error object for display, mapping to i18n keys where applicable.
10
+ *
11
+ * @param error AJV error object
12
+ * @param translateFn Translation function (key, defaultMessage) => string
13
+ * @returns Formatted error message
14
+ */
15
+ export declare function formatValidationError(error: any, translateFn: (key: string, defaultMessage?: string) => string): string;
16
+ /**
17
+ * Format multiple AJV errors for display.
18
+ */
19
+ export declare function formatValidationErrors(errors: any[], translateFn: (key: string, defaultMessage?: string) => string): string[];
@@ -0,0 +1,59 @@
1
+ import { ErrorObject } from 'ajv';
2
+ import { AnimalStockCategory, FarmManureTradingCategory, FarmManureTradingMode, FieldCultivationTab, FieldSpreadingCategory, FodderCategory, FodderMode, PageId, StorageEntryType, StorageTab } from '../navigation/navigation.service';
3
+ export interface EnrichedValidationError extends ErrorObject {
4
+ /** Human-friendly field label (e.g., "Animal Category") */
5
+ fieldLabel?: string;
6
+ /** Navigation target: page */
7
+ targetPage?: PageId;
8
+ /** Navigation target: animal stock array index */
9
+ targetAnimalStockIndex?: number;
10
+ /** Navigation target: detail category (tab) */
11
+ targetCategory?: AnimalStockCategory;
12
+ /** Navigation target: static section (e.g., lifetime performance panel) */
13
+ targetSection?: 'lifetimePerformance';
14
+ /** Navigation target: farm manure trading tab */
15
+ targetFarmManureTradingMode?: FarmManureTradingMode;
16
+ /** Navigation target: farm manure trading entry index */
17
+ targetFarmManureTradingIndex?: number;
18
+ /** Category tab inside farm manure trading detail */
19
+ targetFarmManureTradingCategory?: FarmManureTradingCategory;
20
+ /** Navigation target: fodder mode */
21
+ targetFodderMode?: FodderMode;
22
+ /** Navigation target: fodder entry index */
23
+ targetFodderIndex?: number;
24
+ /** Category tab inside fodder detail */
25
+ targetFodderCategory?: FodderCategory;
26
+ /** Category tab inside field spreading */
27
+ targetFieldSpreadingCategory?: FieldSpreadingCategory;
28
+ /** Category tab inside field cultivation */
29
+ targetFieldCultivationTab?: FieldCultivationTab;
30
+ /** Field cultivation detail index */
31
+ targetFieldCultivationIndex?: number;
32
+ /** Storage detail type */
33
+ targetStorageType?: StorageEntryType;
34
+ /** Storage detail index */
35
+ targetStorageIndex?: number;
36
+ /** Storage tab for list-level or scalar navigation */
37
+ targetStorageTab?: StorageTab;
38
+ }
39
+ /**
40
+ * GlobalValidationService
41
+ * Validates the entire NaebiData structure using the root JSON Schema + AJV.
42
+ * Consolidates errors and enriches them with navigation metadata for deep-linking.
43
+ *
44
+ * Usage: Inject in App or top-level components; errors() signal exposes enriched errors.
45
+ */
46
+ export declare class GlobalValidationService {
47
+ private readonly dataSvc;
48
+ private readonly ajv;
49
+ private readonly validateFn;
50
+ readonly errors: import("@angular/core").Signal<EnrichedValidationError[]>;
51
+ private consolidateErrors;
52
+ private enrichErrors;
53
+ private inferCategory;
54
+ private inferFarmTradingCategory;
55
+ private inferFieldSpreadingCategory;
56
+ private inferFodderCategory;
57
+ private inferStorageTab;
58
+ private inferFieldLabel;
59
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Constraint resolver registry enabling UI schema elements to declare dynamic
3
+ * visibility rules referencing domain-specific predicates. A resolver is a
4
+ * pure function returning a boolean. It receives a contextual accessor for
5
+ * current form data (root object) plus master-data + locale.
6
+ *
7
+ * UI schema structured example:
8
+ * {
9
+ * "type": "Constraint",
10
+ * "options": {
11
+ * "constraint": {
12
+ * "resolver": "animalCategory_isPermittedForConcentratedFeedstuffSummering",
13
+ * "args": ["#/animalCategoryPRIF"],
14
+ * "fallbackVisible": false
15
+ * }
16
+ * },
17
+ * "elements": [ { "type": "Group", ... } ]
18
+ * }
19
+ */
20
+ import { MasterDataService } from '../../core/master-data/master-data.service';
21
+ import { I18nService } from '../../core/i18n/i18n.service';
22
+ export interface ConstraintCall {
23
+ resolver: string;
24
+ args?: unknown[];
25
+ fallbackVisible?: boolean;
26
+ }
27
+ export type ConstraintConfig = ConstraintCall;
28
+ export interface ConstraintContext {
29
+ /** Root data object from JSONForms state */
30
+ data: unknown;
31
+ /** Dereference a JSON Pointer (starts with '#/'); returns undefined if invalid */
32
+ get<T = unknown>(pointer: string): T | undefined;
33
+ /** Master-data service */
34
+ masterData: MasterDataService;
35
+ /** Current locale (from I18nService) */
36
+ locale: string;
37
+ }
38
+ export type ConstraintResolver = (ctx: ConstraintContext, ...args: any[]) => boolean;
39
+ export declare function registerConstraint(name: string, fn: ConstraintResolver): void;
40
+ /**
41
+ * Evaluate a constraint configuration.
42
+ * @param cfg constraint object (or undefined => visible)
43
+ * @param data current form data root
44
+ * @param services injected service wrappers
45
+ * @param ctxOverrides optional context override (testing/extensibility)
46
+ */
47
+ export declare function evaluateConstraint(cfg: ConstraintConfig | undefined, data: unknown, services: {
48
+ masterData: MasterDataService;
49
+ i18n: I18nService;
50
+ }, ctxOverrides?: Partial<ConstraintContext>): boolean;