use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use sqlx::FromRow; use uuid::Uuid; // --- Pagination --- #[derive(Debug, Deserialize)] pub struct PaginationParams { pub page: Option, pub per_page: Option, pub search: Option, } impl PaginationParams { pub fn limit(&self) -> i64 { self.per_page.unwrap_or(25).min(100) } pub fn offset(&self) -> i64 { (self.page.unwrap_or(1) - 1).max(0) * self.limit() } } #[derive(Debug, Serialize)] pub struct PaginatedResponse { pub data: Vec, pub total: i64, pub page: i64, pub per_page: i64, } // --- Families --- #[derive(Debug, FromRow, Serialize)] pub struct Family { pub id: Uuid, pub slug: String, pub name_scientific: String, pub name_en: Option, pub name_de: Option, pub description: Option, pub created_at: DateTime, pub updated_at: DateTime, } #[derive(Debug, Deserialize)] pub struct CreateFamily { pub name_scientific: String, pub name_en: Option, pub name_de: Option, pub description: Option, } #[derive(Debug, Deserialize)] pub struct UpdateFamily { pub name_scientific: Option, pub name_en: Option, pub name_de: Option, pub description: Option, } // --- Species --- #[derive(Debug, FromRow, Serialize)] pub struct Species { pub id: Uuid, pub slug: String, pub family_id: Uuid, pub name_scientific: String, pub name_en: Option, pub name_de: Option, pub description: Option, pub description_de: Option, pub description_en: Option, pub soil_moisture: Option, pub drainage_requirement: Option, pub organic_matter_pct: Option, pub nitrogen_ppm: Option, pub phosphorus_ppm: Option, pub potassium_ppm: Option, pub boron_ppm: Option, pub calcium_ppm: Option, pub copper_ppm: Option, pub iron_ppm: Option, pub magnesium_ppm: Option, pub manganese_ppm: Option, pub molybdenum_ppm: Option, pub sulfur_ppm: Option, pub zinc_ppm: Option, pub ph_min: Option, pub ph_max: Option, pub soil_texture_preference: Option>, pub hardiness_zone_usda: Option, pub hardiness_zone_at: Option, pub min_temp: Option, pub max_temp: Option, pub drought_tolerance: Option, pub water_requirement_mm_week: Option, pub waterlogging_tolerance: Option, pub salt_tolerance: Option, pub edibility_rating: Option, pub food_uses: Option, pub food_uses_de: Option, pub food_uses_en: Option, pub medicinal_uses: Option, pub medicinal_uses_de: Option, pub medicinal_uses_en: Option, pub other_uses: Option, pub other_uses_de: Option, pub other_uses_en: Option, pub native_range: Option, pub native_range_de: Option, pub native_range_en: Option, pub invasiveness: Option, pub pollination_type: Option, pub plant_layer: Option, pub nitrogen_fixer: Option, pub dynamic_accumulator: Option, pub dynamic_accumulator_nutrients: Option>, pub attracts_pollinators: Option, pub attracts_beneficial_insects: Option, pub wildlife_value: Option, pub wildlife_value_de: Option, pub wildlife_value_en: Option, pub mulch_plant: Option, pub ground_cover_quality: Option, pub allelopathic: Option, pub guild_role: Option>, pub succession_stage: Option, pub heavy_metal_tolerance: Option, pub wikidata_qid: Option, pub gbif_id: Option, pub eppo_code: Option, pub pfaf_url: Option, pub nectar_value: Option, pub pollen_value: Option, pub wild_bee_count: Option, pub wild_bee_specialist_count: Option, pub butterfly_moth_count: Option, pub caterpillar_host_count: Option, pub caterpillar_specialist_count: Option, pub hoverfly_count: Option, pub beetle_count: Option, pub bird_count: Option, pub mammal_count: Option, pub native_status: Option, pub naturadb_tags: Option, pub primary_image_key: Option, pub source_urls: Option>, pub created_at: DateTime, pub updated_at: DateTime, } #[derive(Debug, Deserialize)] pub struct CreateSpecies { pub family_id: Uuid, pub name_scientific: String, pub name_en: Option, pub name_de: Option, pub description: Option, pub description_de: Option, pub description_en: Option, pub soil_moisture: Option, pub drainage_requirement: Option, pub ph_min: Option, pub ph_max: Option, pub soil_texture_preference: Option>, pub hardiness_zone_usda: Option, pub hardiness_zone_at: Option, pub min_temp: Option, pub max_temp: Option, pub drought_tolerance: Option, pub salt_tolerance: Option, pub edibility_rating: Option, pub food_uses: Option, pub food_uses_de: Option, pub food_uses_en: Option, pub medicinal_uses: Option, pub medicinal_uses_de: Option, pub medicinal_uses_en: Option, pub other_uses: Option, pub other_uses_de: Option, pub other_uses_en: Option, pub native_range: Option, pub native_range_de: Option, pub native_range_en: Option, pub invasiveness: Option, pub pollination_type: Option, pub plant_layer: Option, pub nitrogen_fixer: Option, pub dynamic_accumulator: Option, pub dynamic_accumulator_nutrients: Option>, pub attracts_pollinators: Option, pub attracts_beneficial_insects: Option, pub wildlife_value: Option, pub wildlife_value_de: Option, pub wildlife_value_en: Option, pub mulch_plant: Option, pub ground_cover_quality: Option, pub allelopathic: Option, pub guild_role: Option>, pub succession_stage: Option, pub heavy_metal_tolerance: Option, pub wikidata_qid: Option, pub gbif_id: Option, pub eppo_code: Option, pub pfaf_url: Option, pub nectar_value: Option, pub pollen_value: Option, pub wild_bee_count: Option, pub wild_bee_specialist_count: Option, pub butterfly_moth_count: Option, pub caterpillar_host_count: Option, pub caterpillar_specialist_count: Option, pub hoverfly_count: Option, pub beetle_count: Option, pub bird_count: Option, pub mammal_count: Option, pub native_status: Option, pub naturadb_tags: Option, pub source_urls: Option>, } pub type UpdateSpecies = CreateSpecies; // --- Cultivars --- #[derive(Debug, FromRow, Serialize)] pub struct Cultivar { pub id: Uuid, pub slug: String, pub species_id: Uuid, pub name: String, pub name_en: Option, pub name_de: Option, pub name_scientific: Option, pub description: Option, pub description_de: Option, pub description_en: Option, pub is_organic: bool, pub perennial: bool, pub growing_time_days: Option, pub planting_depth_cm: Option, pub row_spacing_cm: Option, pub plant_spacing_cm: Option, pub days_to_germination: Option, pub germination_temp_c: Option, pub light_requirement: Option, pub stratification_required: Option, pub stratification_days: Option, pub scarification_required: Option, pub seed_viability_years: Option, pub storage_temp_c: Option, pub storage_humidity: Option, pub storage_notes: Option, pub min_temp: Option, pub max_temp: Option, pub humidity: Option, pub light: Option, pub frost_tolerance: Option, pub min_light_hours_day: Option, pub optimal_light_hours_day: Option, pub greenhouse_min_temp_c: Option, pub indoor_season_extension_weeks: Option, pub ventilation_requirement: Option, pub heating_required: Option, pub indoor_sowing_months: Option>, pub direct_sowing_months: Option>, pub transplanting_months: Option>, pub glasshouse_months: Option>, pub harvesting_months: Option>, pub indoor_sowing_weeks: Option>, pub direct_sowing_weeks: Option>, pub transplanting_weeks: Option>, pub glasshouse_weeks: Option>, pub harvesting_weeks: Option>, pub succession_planting_days: Option, pub planting_notes: Option, pub propagation_methods: Option>, pub cutting_season: Option, pub rootstock_species_id: Option, pub years_to_first_harvest: Option, pub productive_lifespan_years: Option, pub expected_yield_kg_per_m2: Option, pub yield_unit: Option, pub expected_yield_value: Option, pub harvest_window_days: Option, pub storage_method: Option>, pub shelf_life_days: Option, pub cold_storage_days: Option, pub pollination_group: Option, pub self_fertile: Option, pub rootstock_compatibility: Option, pub wikidata_qid: Option, pub gbif_id: Option, pub pfaf_url: Option, pub primary_image_key: Option, pub source_urls: Option>, pub created_at: DateTime, pub updated_at: DateTime, } #[derive(Debug, Deserialize)] pub struct CreateCultivar { pub species_id: Uuid, pub name: String, pub name_en: Option, pub name_de: Option, pub name_scientific: Option, pub description: Option, pub description_de: Option, pub description_en: Option, pub is_organic: Option, pub perennial: Option, pub growing_time_days: Option, pub planting_depth_cm: Option, pub row_spacing_cm: Option, pub plant_spacing_cm: Option, pub days_to_germination: Option, pub germination_temp_c: Option, pub light_requirement: Option, pub stratification_required: Option, pub stratification_days: Option, pub scarification_required: Option, pub seed_viability_years: Option, pub storage_temp_c: Option, pub storage_humidity: Option, pub storage_notes: Option, pub min_temp: Option, pub max_temp: Option, pub humidity: Option, pub light: Option, pub frost_tolerance: Option, pub min_light_hours_day: Option, pub optimal_light_hours_day: Option, pub greenhouse_min_temp_c: Option, pub indoor_season_extension_weeks: Option, pub ventilation_requirement: Option, pub heating_required: Option, pub indoor_sowing_months: Option>, pub direct_sowing_months: Option>, pub transplanting_months: Option>, pub glasshouse_months: Option>, pub harvesting_months: Option>, pub indoor_sowing_weeks: Option>, pub direct_sowing_weeks: Option>, pub transplanting_weeks: Option>, pub glasshouse_weeks: Option>, pub harvesting_weeks: Option>, pub succession_planting_days: Option, pub planting_notes: Option, pub propagation_methods: Option>, pub cutting_season: Option, pub rootstock_species_id: Option, pub years_to_first_harvest: Option, pub productive_lifespan_years: Option, pub expected_yield_kg_per_m2: Option, pub yield_unit: Option, pub expected_yield_value: Option, pub harvest_window_days: Option, pub storage_method: Option>, pub shelf_life_days: Option, pub cold_storage_days: Option, pub pollination_group: Option, pub self_fertile: Option, pub rootstock_compatibility: Option, pub wikidata_qid: Option, pub gbif_id: Option, pub pfaf_url: Option, pub source_urls: Option>, } pub type UpdateCultivar = CreateCultivar; // --- Suppliers --- #[derive(Debug, FromRow, Serialize)] pub struct Supplier { pub id: Uuid, pub slug: String, pub name: String, pub url: Option, pub is_organic: bool, pub is_demeter: bool, pub country: Option, pub notes: Option, pub created_at: DateTime, pub updated_at: DateTime, } #[derive(Debug, Deserialize)] pub struct CreateSupplier { pub name: String, pub url: Option, pub is_organic: Option, pub is_demeter: Option, pub country: Option, pub notes: Option, } pub type UpdateSupplier = CreateSupplier; #[derive(Debug, FromRow, Serialize)] pub struct CultivarSupplier { pub id: Uuid, pub cultivar_id: Uuid, pub supplier_id: Uuid, pub article_number: Option, pub product_url: Option, pub price_eur: Option, pub pack_size: Option, pub pack_unit: Option, pub last_checked_at: Option>, pub created_at: DateTime, } #[derive(Debug, Deserialize)] pub struct CreateCultivarSupplier { pub supplier_id: Uuid, pub article_number: Option, pub product_url: Option, pub price_eur: Option, pub pack_size: Option, pub pack_unit: Option, } // --- Companion Relationships --- #[derive(Debug, FromRow, Serialize)] pub struct CompanionRelationship { pub id: Uuid, pub species_a_id: Uuid, pub species_b_id: Uuid, pub relationship: String, pub mechanism: Option, pub source_url: Option, pub created_at: DateTime, } #[derive(Debug, Deserialize)] pub struct CreateCompanion { pub species_a_id: Uuid, pub species_b_id: Uuid, pub relationship: String, pub mechanism: Option, pub source_url: Option, } // --- Images --- #[derive(Debug, FromRow, Serialize)] pub struct Image { pub id: Uuid, pub entity_type: String, pub entity_id: Uuid, pub s3_key: String, pub caption: Option, pub source_url: Option, pub license: Option, pub is_primary: bool, pub created_at: DateTime, } // --- Users --- #[derive(Debug, FromRow, Serialize)] pub struct User { pub id: Uuid, pub email: String, pub name: Option, pub nickname: Option, pub avatar_url: Option, pub provider: String, pub provider_id: Option, pub admin: bool, pub inserted_at: DateTime, pub updated_at: DateTime, } // --- Search --- #[derive(Debug, Serialize)] pub struct SearchResult { pub entity_type: String, pub id: Uuid, pub slug: String, pub name: String, pub description: Option, pub rank: f32, }