- Add GrowerAdvisoryAgent test file - Fix PlantChain constructor initialization order (plantIndex before genesis block) - Fix blockchain.getChain() calls to use blockchain.chain property - Add PropagationType export to blockchain types - Fix SoilComposition.type property references (was soilType) - Fix ClimateConditions.temperatureDay property references (was avgTemperature) - Fix ClimateConditions.humidityAverage property references (was avgHumidity) - Fix LightingConditions.naturalLight.hoursPerDay nested access - Add 'critical' severity to QualityReport issues - Add 'sqm' unit to PlantingRecommendation.quantityUnit - Fix GrowerAdvisoryAgent growthMetrics property access - Update TypeScript to v5 for react-hook-form compatibility - Enable downlevelIteration in tsconfig for Map iteration - Fix crypto Buffer type issues in anonymity.ts - Fix zones.tsx status type comparison - Fix next.config.js images.domains filter - Rename [[...slug]].tsx to [...slug].tsx to resolve routing conflict
379 lines
8.2 KiB
TypeScript
379 lines
8.2 KiB
TypeScript
/**
|
|
* Demand Forecasting Types for LocalGreenChain
|
|
* Enables demand-driven, seasonal agriculture planning
|
|
*/
|
|
|
|
// Consumer preference for produce
|
|
export interface ConsumerPreference {
|
|
consumerId: string;
|
|
createdAt: string;
|
|
updatedAt: string;
|
|
|
|
// Location for local matching
|
|
location: {
|
|
latitude: number;
|
|
longitude: number;
|
|
maxDeliveryRadiusKm: number;
|
|
city?: string;
|
|
region?: string;
|
|
};
|
|
|
|
// Dietary preferences
|
|
dietaryType: ('omnivore' | 'vegetarian' | 'vegan' | 'pescatarian' | 'flexitarian')[];
|
|
allergies: string[];
|
|
dislikes: string[];
|
|
|
|
// Produce preferences
|
|
preferredCategories: ProduceCategory[];
|
|
preferredItems: ProducePreference[];
|
|
|
|
// Quality preferences
|
|
certificationPreferences: ('organic' | 'non_gmo' | 'biodynamic' | 'local' | 'heirloom')[];
|
|
freshnessImportance: 1 | 2 | 3 | 4 | 5;
|
|
priceImportance: 1 | 2 | 3 | 4 | 5;
|
|
sustainabilityImportance: 1 | 2 | 3 | 4 | 5;
|
|
|
|
// Delivery preferences
|
|
deliveryPreferences: {
|
|
method: ('home_delivery' | 'pickup_point' | 'farmers_market' | 'csa')[];
|
|
frequency: 'daily' | 'twice_weekly' | 'weekly' | 'bi_weekly' | 'monthly';
|
|
preferredDays: ('monday' | 'tuesday' | 'wednesday' | 'thursday' | 'friday' | 'saturday' | 'sunday')[];
|
|
};
|
|
|
|
// Household info
|
|
householdSize: number;
|
|
weeklyBudget?: number;
|
|
currency?: string;
|
|
}
|
|
|
|
export type ProduceCategory =
|
|
| 'leafy_greens'
|
|
| 'root_vegetables'
|
|
| 'nightshades'
|
|
| 'brassicas'
|
|
| 'alliums'
|
|
| 'legumes'
|
|
| 'squash'
|
|
| 'herbs'
|
|
| 'microgreens'
|
|
| 'sprouts'
|
|
| 'mushrooms'
|
|
| 'fruits'
|
|
| 'berries'
|
|
| 'citrus'
|
|
| 'tree_fruits'
|
|
| 'melons'
|
|
| 'edible_flowers';
|
|
|
|
export interface ProducePreference {
|
|
produceType: string;
|
|
category: ProduceCategory;
|
|
priority: 'must_have' | 'preferred' | 'nice_to_have' | 'occasional';
|
|
weeklyQuantity?: number;
|
|
unit?: string;
|
|
varietyPreferences?: string[];
|
|
seasonalOnly: boolean;
|
|
}
|
|
|
|
// Demand signal from aggregated preferences
|
|
export interface DemandSignal {
|
|
id: string;
|
|
timestamp: string;
|
|
|
|
// Location scope
|
|
region: {
|
|
centerLat: number;
|
|
centerLon: number;
|
|
radiusKm: number;
|
|
name: string;
|
|
};
|
|
|
|
// Time scope
|
|
periodStart: string;
|
|
periodEnd: string;
|
|
seasonalPeriod: 'spring' | 'summer' | 'fall' | 'winter';
|
|
|
|
// Aggregated demand
|
|
demandItems: DemandItem[];
|
|
|
|
// Statistics
|
|
totalConsumers: number;
|
|
totalWeeklyDemandKg: number;
|
|
confidenceLevel: number; // 0-100
|
|
|
|
// Supply status
|
|
currentSupplyKg: number;
|
|
supplyGapKg: number;
|
|
supplyStatus: 'surplus' | 'balanced' | 'shortage' | 'critical';
|
|
}
|
|
|
|
export interface DemandItem {
|
|
produceType: string;
|
|
category: ProduceCategory;
|
|
scientificName?: string;
|
|
|
|
// Quantities
|
|
weeklyDemandKg: number;
|
|
monthlyDemandKg: number;
|
|
consumerCount: number;
|
|
|
|
// Priority
|
|
aggregatePriority: number; // 1-10
|
|
urgency: 'immediate' | 'this_week' | 'this_month' | 'next_season';
|
|
|
|
// Preferences
|
|
preferredCertifications: string[];
|
|
averageWillingPrice: number;
|
|
priceUnit: string;
|
|
|
|
// Seasonal info
|
|
inSeason: boolean;
|
|
seasonalAvailability: {
|
|
spring: boolean;
|
|
summer: boolean;
|
|
fall: boolean;
|
|
winter: boolean;
|
|
};
|
|
|
|
// Supply matching
|
|
matchedSupply: number;
|
|
matchedGrowers: number;
|
|
gapKg: number;
|
|
}
|
|
|
|
// Grower planting recommendation
|
|
export interface PlantingRecommendation {
|
|
id: string;
|
|
timestamp: string;
|
|
growerId: string;
|
|
|
|
// Recommendation details
|
|
produceType: string;
|
|
variety?: string;
|
|
category: ProduceCategory;
|
|
|
|
// Quantities
|
|
recommendedQuantity: number;
|
|
quantityUnit: 'plants' | 'seeds' | 'kg_expected_yield' | 'sqm';
|
|
expectedYieldKg: number;
|
|
yieldConfidence: number; // 0-100
|
|
|
|
// Timing
|
|
plantByDate: string;
|
|
expectedHarvestStart: string;
|
|
expectedHarvestEnd: string;
|
|
growingDays: number;
|
|
|
|
// Market opportunity
|
|
projectedDemandKg: number;
|
|
projectedPricePerKg: number;
|
|
projectedRevenue: number;
|
|
marketConfidence: number; // 0-100
|
|
|
|
// Risk assessment
|
|
riskFactors: RiskFactor[];
|
|
overallRisk: 'low' | 'medium' | 'high';
|
|
|
|
// Reasoning
|
|
demandSignalIds: string[];
|
|
explanation: string;
|
|
}
|
|
|
|
export interface RiskFactor {
|
|
type: 'weather' | 'pest' | 'disease' | 'market' | 'oversupply' | 'labor' | 'transport';
|
|
severity: 'low' | 'medium' | 'high';
|
|
description: string;
|
|
mitigationSuggestion?: string;
|
|
}
|
|
|
|
// Seasonal planning
|
|
export interface SeasonalPlan {
|
|
id: string;
|
|
growerId: string;
|
|
year: number;
|
|
season: 'spring' | 'summer' | 'fall' | 'winter';
|
|
|
|
// Location context
|
|
location: {
|
|
latitude: number;
|
|
longitude: number;
|
|
hardinessZone: string;
|
|
microclimate?: string;
|
|
};
|
|
|
|
// Growing capacity
|
|
growingCapacity: {
|
|
outdoorSqMeters?: number;
|
|
greenhouseSqMeters?: number;
|
|
verticalFarmSqMeters?: number;
|
|
hydroponicUnits?: number;
|
|
};
|
|
|
|
// Planned crops
|
|
plannedCrops: PlannedCrop[];
|
|
|
|
// Expected outcomes
|
|
expectedTotalYieldKg: number;
|
|
expectedRevenue: number;
|
|
expectedCarbonFootprintKg: number;
|
|
|
|
// Status
|
|
status: 'draft' | 'confirmed' | 'in_progress' | 'completed';
|
|
completionPercentage?: number;
|
|
}
|
|
|
|
export interface PlannedCrop {
|
|
produceType: string;
|
|
variety?: string;
|
|
|
|
// Planting
|
|
plantingDate: string;
|
|
plantingMethod: 'direct_sow' | 'transplant' | 'hydroponic' | 'aeroponic';
|
|
quantity: number;
|
|
quantityUnit: 'plants' | 'seeds' | 'sqm' | 'units';
|
|
|
|
// Space allocation
|
|
allocatedSpace: number;
|
|
spaceUnit: 'sqm' | 'sqft' | 'units';
|
|
growingLocation: 'outdoor' | 'greenhouse' | 'vertical_farm' | 'indoor';
|
|
|
|
// Expected harvest
|
|
expectedHarvestStart: string;
|
|
expectedHarvestEnd: string;
|
|
expectedYieldKg: number;
|
|
|
|
// Market allocation
|
|
preCommittedKg: number;
|
|
preCommittedTo: string[]; // consumer IDs or market names
|
|
|
|
// Status
|
|
status: 'planned' | 'planted' | 'growing' | 'harvesting' | 'completed' | 'failed';
|
|
actualYieldKg?: number;
|
|
}
|
|
|
|
// Demand forecast model
|
|
export interface DemandForecast {
|
|
id: string;
|
|
generatedAt: string;
|
|
|
|
// Scope
|
|
region: string;
|
|
forecastPeriod: {
|
|
start: string;
|
|
end: string;
|
|
};
|
|
|
|
// Forecasts by produce type
|
|
forecasts: ProduceForecast[];
|
|
|
|
// Model info
|
|
modelVersion: string;
|
|
dataPointsUsed: number;
|
|
lastTrainingDate: string;
|
|
}
|
|
|
|
export interface ProduceForecast {
|
|
produceType: string;
|
|
category: ProduceCategory;
|
|
|
|
// Predicted demand
|
|
predictedDemandKg: number;
|
|
confidenceInterval: {
|
|
low: number;
|
|
high: number;
|
|
};
|
|
confidence: number; // 0-100
|
|
|
|
// Trends
|
|
trend: 'increasing' | 'stable' | 'decreasing';
|
|
trendStrength: number; // 0-100
|
|
seasonalFactor: number; // multiplier
|
|
|
|
// Price prediction
|
|
predictedPricePerKg: number;
|
|
priceConfidenceInterval: {
|
|
low: number;
|
|
high: number;
|
|
};
|
|
|
|
// Influencing factors
|
|
factors: ForecastFactor[];
|
|
}
|
|
|
|
export interface ForecastFactor {
|
|
name: string;
|
|
type: 'seasonal' | 'trend' | 'event' | 'weather' | 'economic' | 'preference';
|
|
impact: number; // -100 to +100
|
|
description: string;
|
|
}
|
|
|
|
// Supply commitment from grower
|
|
export interface SupplyCommitment {
|
|
id: string;
|
|
growerId: string;
|
|
timestamp: string;
|
|
|
|
produceType: string;
|
|
variety?: string;
|
|
|
|
// Commitment details
|
|
committedQuantityKg: number;
|
|
availableFrom: string;
|
|
availableUntil: string;
|
|
|
|
// Pricing
|
|
pricePerKg: number;
|
|
currency: string;
|
|
minimumOrderKg: number;
|
|
bulkDiscountThreshold?: number;
|
|
bulkDiscountPercent?: number;
|
|
|
|
// Quality
|
|
certifications: string[];
|
|
freshnessGuaranteeHours: number;
|
|
|
|
// Delivery
|
|
deliveryRadiusKm: number;
|
|
deliveryMethods: ('grower_delivery' | 'customer_pickup' | 'hub_dropoff' | 'third_party')[];
|
|
|
|
// Status
|
|
status: 'available' | 'partially_committed' | 'fully_committed' | 'expired';
|
|
remainingKg: number;
|
|
}
|
|
|
|
// Market match between supply and demand
|
|
export interface MarketMatch {
|
|
id: string;
|
|
timestamp: string;
|
|
|
|
demandSignalId: string;
|
|
supplyCommitmentId: string;
|
|
|
|
consumerId: string;
|
|
growerId: string;
|
|
|
|
produceType: string;
|
|
matchedQuantityKg: number;
|
|
|
|
// Transaction details
|
|
agreedPricePerKg: number;
|
|
totalPrice: number;
|
|
currency: string;
|
|
|
|
// Delivery
|
|
deliveryDate: string;
|
|
deliveryMethod: string;
|
|
deliveryLocation: {
|
|
latitude: number;
|
|
longitude: number;
|
|
address?: string;
|
|
};
|
|
|
|
// Status
|
|
status: 'pending' | 'confirmed' | 'in_transit' | 'delivered' | 'completed' | 'cancelled';
|
|
|
|
// Ratings
|
|
consumerRating?: number;
|
|
growerRating?: number;
|
|
feedback?: string;
|
|
}
|