UPDATE
This commit is contained in:
@@ -0,0 +1,341 @@
|
||||
# Fertilization Recommendation API Fields
|
||||
|
||||
این فایل فقط فیلدهای API مربوط به `POST /api/fertilization/recommend/` را توضیح میدهد.
|
||||
|
||||
## Endpoint
|
||||
|
||||
`POST /api/fertilization/recommend/`
|
||||
|
||||
## ساختار کلی پاسخ
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"msg": "success",
|
||||
"data": {
|
||||
"primary_recommendation": {},
|
||||
"nutrient_analysis": {},
|
||||
"application_guide": {},
|
||||
"alternative_recommendations": [],
|
||||
"sections": []
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## فیلدهای Request
|
||||
|
||||
### `farm_uuid`
|
||||
- نوع: `string`
|
||||
- اجباری: بله
|
||||
- توضیح: شناسه یکتای مزرعه که توصیه برای آن تولید میشود.
|
||||
|
||||
### `sensor_uuid`
|
||||
- نوع: `string`
|
||||
- اجباری: خیر
|
||||
- توضیح: نام قدیمی برای `farm_uuid`. اگر `farm_uuid` ارسال نشده باشد، این مقدار به جای آن استفاده میشود.
|
||||
|
||||
### `crop_id`
|
||||
- نوع: `string`
|
||||
- اجباری: خیر
|
||||
- توضیح: شناسه یا نام محصول. اگر `plant_name` ارسال نشده باشد، همین مقدار به عنوان نام گیاه استفاده میشود.
|
||||
|
||||
### `plant_name`
|
||||
- نوع: `string`
|
||||
- اجباری: خیر
|
||||
- توضیح: نام گیاه یا محصول هدف برای تولید توصیه.
|
||||
|
||||
### `growth_stage`
|
||||
- نوع: `string`
|
||||
- اجباری: خیر
|
||||
- توضیح: مرحله رشد گیاه مثل `flowering` یا `fruiting`.
|
||||
|
||||
### `query`
|
||||
- نوع: `string`
|
||||
- اجباری: خیر
|
||||
- توضیح: سوال یا درخواست متنی اختیاری برای جهت دادن به توصیه.
|
||||
|
||||
## فیلدهای لایه اول Response
|
||||
|
||||
### `code`
|
||||
- نوع: `number`
|
||||
- توضیح: کد وضعیت پاسخ در قالب استاندارد API پروژه.
|
||||
|
||||
### `msg`
|
||||
- نوع: `string`
|
||||
- توضیح: پیام وضعیت پاسخ. در حالت موفق معمولاً `success` است.
|
||||
|
||||
### `data`
|
||||
- نوع: `object`
|
||||
- توضیح: بدنه اصلی توصیه کودهی ساختاریافته.
|
||||
|
||||
## فیلدهای `data`
|
||||
|
||||
### `primary_recommendation`
|
||||
- نوع: `object`
|
||||
- توضیح: پیشنهاد اصلی کودهی که فرانت باید در Hero Card و ماشین حساب مصرف از آن استفاده کند.
|
||||
|
||||
### `nutrient_analysis`
|
||||
- نوع: `object`
|
||||
- توضیح: تحلیل ساختاریافته عناصر غذایی اصلی و ریزمغذیها.
|
||||
|
||||
### `application_guide`
|
||||
- نوع: `object`
|
||||
- توضیح: هشدار ایمنی و مراحل اجرای مصرف.
|
||||
|
||||
### `alternative_recommendations`
|
||||
- نوع: `array`
|
||||
- توضیح: فهرست کودهای جایگزین قابل استفاده در شرایط مشابه.
|
||||
|
||||
### `sections`
|
||||
- نوع: `array`
|
||||
- توضیح: ساختار legacy برای سازگاری با فرانت یا کلاینتهای قدیمی.
|
||||
|
||||
## فیلدهای `data.primary_recommendation`
|
||||
|
||||
### `fertilizer_code`
|
||||
- نوع: `string`
|
||||
- توضیح: کد یکتای کود پیشنهادی.
|
||||
|
||||
### `fertilizer_name`
|
||||
- نوع: `string`
|
||||
- توضیح: نام اصلی کود پیشنهادی برای نمایش.
|
||||
|
||||
### `display_title`
|
||||
- نوع: `string`
|
||||
- توضیح: عنوان نمایشی آماده برای کارت اصلی.
|
||||
|
||||
### `fertilizer_type`
|
||||
- نوع: `string`
|
||||
- توضیح: نوع کود مثل `NPK`.
|
||||
|
||||
### `npk_ratio`
|
||||
- نوع: `object`
|
||||
- توضیح: نسبت NPK به صورت ساختاریافته.
|
||||
|
||||
### `application_method`
|
||||
- نوع: `object`
|
||||
- توضیح: روش مصرف کود.
|
||||
|
||||
### `application_interval`
|
||||
- نوع: `object`
|
||||
- توضیح: فاصله زمانی پیشنهادی بین دفعات مصرف.
|
||||
|
||||
### `dosage`
|
||||
- نوع: `object`
|
||||
- توضیح: مقادیر پایه مصرف که فرانت با آنها مقدار مورد نیاز را حساب میکند.
|
||||
|
||||
### `reasoning`
|
||||
- نوع: `string`
|
||||
- توضیح: توضیح علمی و عملی درباره دلیل انتخاب این توصیه.
|
||||
|
||||
### `summary`
|
||||
- نوع: `string`
|
||||
- توضیح: خلاصه کوتاه و مناسب نمایش در بخش اصلی فرانت.
|
||||
|
||||
## فیلدهای `data.primary_recommendation.npk_ratio`
|
||||
|
||||
### `n`
|
||||
- نوع: `number`
|
||||
- توضیح: درصد نیتروژن در کود پیشنهادی.
|
||||
|
||||
### `p`
|
||||
- نوع: `number`
|
||||
- توضیح: درصد فسفر در کود پیشنهادی.
|
||||
|
||||
### `k`
|
||||
- نوع: `number`
|
||||
- توضیح: درصد پتاسیم در کود پیشنهادی.
|
||||
|
||||
### `label`
|
||||
- نوع: `string`
|
||||
- توضیح: نمایش متنی نسبت NPK مثل `20-20-20`.
|
||||
|
||||
## فیلدهای `data.primary_recommendation.application_method`
|
||||
|
||||
### `id`
|
||||
- نوع: `string`
|
||||
- توضیح: شناسه استاندارد روش مصرف مثل `fertigation` یا `foliar_fertigation`.
|
||||
|
||||
### `label`
|
||||
- نوع: `string`
|
||||
- توضیح: متن آماده نمایش برای روش مصرف.
|
||||
|
||||
## فیلدهای `data.primary_recommendation.application_interval`
|
||||
|
||||
### `value`
|
||||
- نوع: `number`
|
||||
- توضیح: فاصله مصرف به صورت عددی.
|
||||
|
||||
### `unit`
|
||||
- نوع: `string`
|
||||
- توضیح: واحد فاصله مصرف مثل `day`.
|
||||
|
||||
### `label`
|
||||
- نوع: `string`
|
||||
- توضیح: متن آماده نمایش مثل `هر 14 روز`.
|
||||
|
||||
## فیلدهای `data.primary_recommendation.dosage`
|
||||
|
||||
### `base_amount_per_hectare`
|
||||
- نوع: `number`
|
||||
- توضیح: مقدار پایه مصرف در هر هکتار.
|
||||
|
||||
### `base_amount_per_square_meter`
|
||||
- نوع: `number`
|
||||
- توضیح: مقدار پایه مصرف در هر متر مربع.
|
||||
|
||||
### `unit`
|
||||
- نوع: `string`
|
||||
- توضیح: واحد مقدار مصرف مثل `kg`.
|
||||
|
||||
### `label`
|
||||
- نوع: `string`
|
||||
- توضیح: متن آماده نمایش دوز مثل `65 کیلوگرم در هکتار`.
|
||||
|
||||
### `calculation_basis`
|
||||
- نوع: `string`
|
||||
- توضیح: مبنای محاسبه دوز؛ معمولاً نام engine یا منبع محاسبه است.
|
||||
|
||||
## نکته محاسبه برای فرانت
|
||||
|
||||
فرانت باید مقدار نهایی را خودش با استفاده از نسبت پایه محاسبه کند.
|
||||
|
||||
فرمول پیشنهادی:
|
||||
|
||||
```text
|
||||
مقدار کل = base_amount_per_square_meter × مساحت مزرعه
|
||||
```
|
||||
|
||||
## فیلدهای `data.nutrient_analysis`
|
||||
|
||||
### `macro`
|
||||
- نوع: `array`
|
||||
- توضیح: لیست عناصر اصلی شامل N، P و K.
|
||||
|
||||
### `micro`
|
||||
- نوع: `array`
|
||||
- توضیح: لیست ریزمغذیها مثل آهن، روی، منگنز و غیره. ممکن است خالی باشد.
|
||||
|
||||
## فیلدهای هر آیتم در `data.nutrient_analysis.macro[]` و `data.nutrient_analysis.micro[]`
|
||||
|
||||
### `key`
|
||||
- نوع: `string`
|
||||
- توضیح: کلید استاندارد عنصر مثل `n`، `p`، `k`، `fe` یا `zn`.
|
||||
|
||||
### `name`
|
||||
- نوع: `string`
|
||||
- توضیح: نام نمایشی عنصر.
|
||||
|
||||
### `value`
|
||||
- نوع: `number`
|
||||
- توضیح: مقدار عنصر، معمولاً به صورت درصد.
|
||||
|
||||
### `unit`
|
||||
- نوع: `string`
|
||||
- توضیح: واحد عنصر، معمولاً `percent`.
|
||||
|
||||
### `description`
|
||||
- نوع: `string`
|
||||
- توضیح: توضیح کوتاه درباره نقش یا اهمیت آن عنصر.
|
||||
|
||||
## فیلدهای `data.application_guide`
|
||||
|
||||
### `safety_warning`
|
||||
- نوع: `string`
|
||||
- توضیح: هشدار ایمنی و اجرایی قبل از مصرف.
|
||||
|
||||
### `steps`
|
||||
- نوع: `array`
|
||||
- توضیح: مراحل پیشنهادی اجرا.
|
||||
|
||||
## فیلدهای هر آیتم در `data.application_guide.steps[]`
|
||||
|
||||
### `step_number`
|
||||
- نوع: `number`
|
||||
- توضیح: شماره مرحله اجرا.
|
||||
|
||||
### `title`
|
||||
- نوع: `string`
|
||||
- توضیح: عنوان کوتاه مرحله.
|
||||
|
||||
### `description`
|
||||
- نوع: `string`
|
||||
- توضیح: توضیح کامل مرحله.
|
||||
|
||||
## فیلدهای هر آیتم در `data.alternative_recommendations[]`
|
||||
|
||||
### `fertilizer_code`
|
||||
- نوع: `string`
|
||||
- توضیح: کد یکتای کود جایگزین.
|
||||
|
||||
### `fertilizer_name`
|
||||
- نوع: `string`
|
||||
- توضیح: نام کود جایگزین.
|
||||
|
||||
### `fertilizer_type`
|
||||
- نوع: `string`
|
||||
- توضیح: نوع کود جایگزین.
|
||||
|
||||
### `usage_method`
|
||||
- نوع: `string`
|
||||
- توضیح: روش مصرف کود جایگزین.
|
||||
|
||||
### `description`
|
||||
- نوع: `string`
|
||||
- توضیح: توضیح اینکه این جایگزین در چه شرایطی مفید است.
|
||||
|
||||
## فیلدهای هر آیتم در `data.sections[]`
|
||||
|
||||
### `type`
|
||||
- نوع: `string`
|
||||
- توضیح: نوع بخش مثل `recommendation`، `list` یا `warning`.
|
||||
|
||||
### `title`
|
||||
- نوع: `string`
|
||||
- توضیح: عنوان بخش.
|
||||
|
||||
### `icon`
|
||||
- نوع: `string`
|
||||
- توضیح: آیکون نمایشی بخش.
|
||||
|
||||
### `content`
|
||||
- نوع: `string`
|
||||
- توضیح: متن اصلی بخش.
|
||||
|
||||
### `items`
|
||||
- نوع: `array`
|
||||
- توضیح: لیست آیتمهای متنی برای بخشهای لیستی.
|
||||
|
||||
### `fertilizerType`
|
||||
- نوع: `string`
|
||||
- توضیح: نسخه legacy نوع کود برای نمایش در کلاینتهای قدیمی.
|
||||
|
||||
### `amount`
|
||||
- نوع: `string`
|
||||
- توضیح: نسخه legacy مقدار مصرف برای کلاینتهای قدیمی.
|
||||
|
||||
### `applicationMethod`
|
||||
- نوع: `string`
|
||||
- توضیح: نسخه legacy روش مصرف.
|
||||
|
||||
### `timing`
|
||||
- نوع: `string`
|
||||
- توضیح: نسخه legacy زمان مناسب اجرا.
|
||||
|
||||
### `validityPeriod`
|
||||
- نوع: `string`
|
||||
- توضیح: نسخه legacy مدت اعتبار توصیه.
|
||||
|
||||
### `expandableExplanation`
|
||||
- نوع: `string`
|
||||
- توضیح: نسخه legacy توضیح کاملتر برای نمایش بازشونده.
|
||||
|
||||
## فیلدهای حذف شده
|
||||
|
||||
فیلدهای زیر دیگر در خروجی اصلی استفاده نمیشوند:
|
||||
|
||||
- `recommendation_id`
|
||||
- `crop`
|
||||
- `growth_stage`
|
||||
- `total_amount`
|
||||
- `area` در request
|
||||
@@ -14,6 +14,7 @@ class FertilizationConfig(AppConfig):
|
||||
return {
|
||||
"simulation_model": "Wofost81_NWLP_CWB_CNB",
|
||||
"validity_days": 7,
|
||||
"default_application_interval_days": 14,
|
||||
"rain_delay_threshold_mm": 3.0,
|
||||
"stage_targets": {
|
||||
"initial": {
|
||||
@@ -23,6 +24,7 @@ class FertilizationConfig(AppConfig):
|
||||
"formula": "10-52-10",
|
||||
"application_method": "استارتر نواری یا همراه آب آبیاری",
|
||||
"timing": "همزمان با استقرار بوته و در ساعات خنک روز",
|
||||
"application_interval_days": 10,
|
||||
},
|
||||
"vegetative": {
|
||||
"n": 55.0,
|
||||
@@ -31,6 +33,7 @@ class FertilizationConfig(AppConfig):
|
||||
"formula": "20-20-20",
|
||||
"application_method": "کودآبیاری یا سرک خاکی سبک",
|
||||
"timing": "صبح زود و ترجیحا قبل از نوبت آبیاری",
|
||||
"application_interval_days": 12,
|
||||
},
|
||||
"flowering": {
|
||||
"n": 42.0,
|
||||
@@ -39,6 +42,7 @@ class FertilizationConfig(AppConfig):
|
||||
"formula": "15-10-30",
|
||||
"application_method": "کودآبیاری یا محلول پاشی سبک",
|
||||
"timing": "صبح زود و دور از تنش گرمایی ظهر",
|
||||
"application_interval_days": 14,
|
||||
},
|
||||
"fruiting": {
|
||||
"n": 35.0,
|
||||
@@ -47,6 +51,7 @@ class FertilizationConfig(AppConfig):
|
||||
"formula": "12-12-36",
|
||||
"application_method": "کودآبیاری با تاکید بر پتاس",
|
||||
"timing": "صبح زود یا نزدیک غروب",
|
||||
"application_interval_days": 10,
|
||||
},
|
||||
},
|
||||
"strategy_profiles": [
|
||||
|
||||
@@ -4,8 +4,9 @@ from rest_framework import serializers
|
||||
class FertilizationRecommendRequestSerializer(serializers.Serializer):
|
||||
"""سریالایزر ورودی برای درخواست توصیه کودهی."""
|
||||
|
||||
farm_uuid = serializers.CharField(required=False, help_text="شناسه یکتای مزرعه (اجباری)")
|
||||
farm_uuid = serializers.CharField(required=False, help_text="شناسه یکتای مزرعه")
|
||||
sensor_uuid = serializers.CharField(required=False, help_text="نام قدیمی برای farm_uuid")
|
||||
crop_id = serializers.CharField(required=False, allow_blank=True, help_text="شناسه یا نام محصول")
|
||||
plant_name = serializers.CharField(required=False, allow_blank=True, help_text="نام گیاه")
|
||||
growth_stage = serializers.CharField(required=False, allow_blank=True, help_text="مرحله رشد گیاه")
|
||||
query = serializers.CharField(required=False, allow_blank=True, help_text="سوال اختیاری")
|
||||
@@ -14,15 +15,103 @@ class FertilizationRecommendRequestSerializer(serializers.Serializer):
|
||||
farm_uuid = attrs.get("farm_uuid") or attrs.get("sensor_uuid")
|
||||
if not farm_uuid:
|
||||
raise serializers.ValidationError({"farm_uuid": "farm_uuid الزامی است."})
|
||||
|
||||
crop_id = (attrs.get("crop_id") or "").strip()
|
||||
plant_name = (attrs.get("plant_name") or "").strip()
|
||||
if crop_id and not plant_name:
|
||||
attrs["plant_name"] = crop_id
|
||||
attrs["farm_uuid"] = farm_uuid
|
||||
return attrs
|
||||
|
||||
|
||||
class FertilizationPlanSerializer(serializers.Serializer):
|
||||
"""سریالایزر خروجی برای پلن توصیه کودهی."""
|
||||
class NpkRatioSerializer(serializers.Serializer):
|
||||
n = serializers.FloatField()
|
||||
p = serializers.FloatField()
|
||||
k = serializers.FloatField()
|
||||
label = serializers.CharField()
|
||||
|
||||
npkRatio = serializers.CharField(help_text="نسبت NPK مثل 20-20-20 (NPK)")
|
||||
amountPerHectare = serializers.CharField(help_text="مقدار مصرف در هکتار مثل 150 kg/ha")
|
||||
applicationMethod = serializers.CharField(help_text="روش مصرف کود")
|
||||
applicationInterval = serializers.CharField(help_text="فاصله زمانی مصرف")
|
||||
reasoning = serializers.CharField(help_text="توضیح دقیق دلیل انتخاب برنامه کودهی")
|
||||
|
||||
class FertilizationApplicationMethodSerializer(serializers.Serializer):
|
||||
id = serializers.CharField()
|
||||
label = serializers.CharField()
|
||||
|
||||
|
||||
class FertilizationApplicationIntervalSerializer(serializers.Serializer):
|
||||
value = serializers.IntegerField()
|
||||
unit = serializers.CharField()
|
||||
label = serializers.CharField()
|
||||
|
||||
|
||||
class FertilizationDosageSerializer(serializers.Serializer):
|
||||
base_amount_per_hectare = serializers.FloatField()
|
||||
base_amount_per_square_meter = serializers.FloatField()
|
||||
unit = serializers.CharField()
|
||||
label = serializers.CharField()
|
||||
calculation_basis = serializers.CharField()
|
||||
|
||||
|
||||
class PrimaryFertilizationRecommendationSerializer(serializers.Serializer):
|
||||
fertilizer_code = serializers.CharField()
|
||||
fertilizer_name = serializers.CharField()
|
||||
display_title = serializers.CharField()
|
||||
fertilizer_type = serializers.CharField()
|
||||
npk_ratio = NpkRatioSerializer()
|
||||
application_method = FertilizationApplicationMethodSerializer()
|
||||
application_interval = FertilizationApplicationIntervalSerializer()
|
||||
dosage = FertilizationDosageSerializer()
|
||||
reasoning = serializers.CharField()
|
||||
summary = serializers.CharField()
|
||||
|
||||
|
||||
class FertilizationNutrientSerializer(serializers.Serializer):
|
||||
key = serializers.CharField()
|
||||
name = serializers.CharField()
|
||||
value = serializers.FloatField()
|
||||
unit = serializers.CharField()
|
||||
description = serializers.CharField(required=False, allow_blank=True)
|
||||
|
||||
|
||||
class FertilizationNutrientAnalysisSerializer(serializers.Serializer):
|
||||
macro = FertilizationNutrientSerializer(many=True)
|
||||
micro = FertilizationNutrientSerializer(many=True)
|
||||
|
||||
|
||||
class FertilizationGuideStepSerializer(serializers.Serializer):
|
||||
step_number = serializers.IntegerField()
|
||||
title = serializers.CharField()
|
||||
description = serializers.CharField()
|
||||
|
||||
|
||||
class FertilizationApplicationGuideSerializer(serializers.Serializer):
|
||||
safety_warning = serializers.CharField()
|
||||
steps = FertilizationGuideStepSerializer(many=True)
|
||||
|
||||
|
||||
class AlternativeFertilizationRecommendationSerializer(serializers.Serializer):
|
||||
fertilizer_code = serializers.CharField()
|
||||
fertilizer_name = serializers.CharField()
|
||||
fertilizer_type = serializers.CharField()
|
||||
usage_method = serializers.CharField()
|
||||
description = serializers.CharField()
|
||||
|
||||
|
||||
class FertilizationSectionSerializer(serializers.Serializer):
|
||||
type = serializers.CharField()
|
||||
title = serializers.CharField()
|
||||
icon = serializers.CharField(required=False, allow_blank=True)
|
||||
content = serializers.CharField(required=False, allow_blank=True)
|
||||
items = serializers.ListField(child=serializers.CharField(), required=False)
|
||||
fertilizerType = serializers.CharField(required=False, allow_blank=True)
|
||||
amount = serializers.CharField(required=False, allow_blank=True)
|
||||
applicationMethod = serializers.CharField(required=False, allow_blank=True)
|
||||
timing = serializers.CharField(required=False, allow_blank=True)
|
||||
validityPeriod = serializers.CharField(required=False, allow_blank=True)
|
||||
expandableExplanation = serializers.CharField(required=False, allow_blank=True)
|
||||
|
||||
|
||||
class FertilizationRecommendationResponseDataSerializer(serializers.Serializer):
|
||||
primary_recommendation = PrimaryFertilizationRecommendationSerializer()
|
||||
nutrient_analysis = FertilizationNutrientAnalysisSerializer()
|
||||
application_guide = FertilizationApplicationGuideSerializer()
|
||||
alternative_recommendations = AlternativeFertilizationRecommendationSerializer(many=True)
|
||||
sections = FertilizationSectionSerializer(many=True, required=False)
|
||||
|
||||
+75
-33
@@ -1,18 +1,14 @@
|
||||
from drf_spectacular.utils import (
|
||||
OpenApiExample,
|
||||
OpenApiResponse,
|
||||
extend_schema,
|
||||
)
|
||||
from drf_spectacular.utils import OpenApiExample, extend_schema
|
||||
from rest_framework import status
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from config.openapi import (
|
||||
build_envelope_serializer,
|
||||
build_response,
|
||||
)
|
||||
from config.openapi import build_envelope_serializer, build_response
|
||||
|
||||
from .serializers import FertilizationRecommendRequestSerializer
|
||||
from .serializers import (
|
||||
FertilizationRecommendationResponseDataSerializer,
|
||||
FertilizationRecommendRequestSerializer,
|
||||
)
|
||||
|
||||
|
||||
FertilizationValidationErrorSerializer = build_envelope_serializer(
|
||||
@@ -22,32 +18,27 @@ FertilizationValidationErrorSerializer = build_envelope_serializer(
|
||||
)
|
||||
FertilizationResponseSerializer = build_envelope_serializer(
|
||||
"FertilizationResponseSerializer",
|
||||
data_schema=None,
|
||||
data_schema=FertilizationRecommendationResponseDataSerializer,
|
||||
)
|
||||
|
||||
|
||||
class FertilizationRecommendView(APIView):
|
||||
"""
|
||||
توصیه کودهی به صورت مستقیم.
|
||||
POST با farm_uuid، plant_name، growth_stage.
|
||||
اطلاعات گیاه از plant app دریافت میشود.
|
||||
نیازی به دریافت نوع آبیاری نیست.
|
||||
توصیه کودهی ساختاریافته با ترکیب RAG و optimizer شبیه سازی.
|
||||
"""
|
||||
|
||||
@extend_schema(
|
||||
tags=["Fertilization Recommendation"],
|
||||
summary="درخواست توصیه کودهی",
|
||||
summary="درخواست توصیه کودهی ساختاریافته",
|
||||
description=(
|
||||
"دادههای سنسور و گیاه را دریافت کرده و "
|
||||
"توصیه کودهی را مستقیم برمیگرداند. "
|
||||
"اطلاعات گیاه از جدول Plant بارگذاری میشود. "
|
||||
"محاسبات مربوط به نیاز آبی در این endpoint انجام نمیشود و مستقل از توصیه کودهی است."
|
||||
"داده های مزرعه، گیاه و مرحله رشد را دریافت می کند و "
|
||||
"خروجی نهایی بهینه شده با ترکیب RAG و optimizer مبتنی بر crop_simulation/PCSE را برمی گرداند."
|
||||
),
|
||||
request=FertilizationRecommendRequestSerializer,
|
||||
responses={
|
||||
200: build_response(
|
||||
FertilizationResponseSerializer,
|
||||
"توصیه کودهی با موفقیت تولید شد.",
|
||||
"توصیه کودهی ساختاریافته با موفقیت تولید شد.",
|
||||
),
|
||||
400: build_response(
|
||||
FertilizationValidationErrorSerializer,
|
||||
@@ -63,11 +54,63 @@ class FertilizationRecommendView(APIView):
|
||||
"نمونه درخواست",
|
||||
value={
|
||||
"farm_uuid": "11111111-1111-1111-1111-111111111111",
|
||||
"plant_name": "گوجهفرنگی",
|
||||
"growth_stage": "گلدهی",
|
||||
"crop_id": "wheat",
|
||||
"growth_stage": "flowering",
|
||||
},
|
||||
request_only=True,
|
||||
),
|
||||
OpenApiExample(
|
||||
"نمونه پاسخ",
|
||||
value={
|
||||
"code": 200,
|
||||
"msg": "success",
|
||||
"data": {
|
||||
"primary_recommendation": {
|
||||
"fertilizer_code": "15-10-30",
|
||||
"fertilizer_name": "کود کامل 15-10-30",
|
||||
"display_title": "کود کامل 15-10-30",
|
||||
"fertilizer_type": "NPK",
|
||||
"npk_ratio": {"n": 15, "p": 10, "k": 30, "label": "15-10-30"},
|
||||
"application_method": {
|
||||
"id": "foliar_fertigation",
|
||||
"label": "کودآبیاری یا محلول پاشی سبک",
|
||||
},
|
||||
"application_interval": {"value": 14, "unit": "day", "label": "هر 14 روز"},
|
||||
"dosage": {
|
||||
"base_amount_per_hectare": 65,
|
||||
"base_amount_per_square_meter": 0.0065,
|
||||
"unit": "kg",
|
||||
"label": "65 کیلوگرم در هکتار",
|
||||
"calculation_basis": "crop_simulation_heuristic",
|
||||
},
|
||||
"reasoning": "این ترکیب برای مرحله گلدهی و توازن نیازهای تغذیه ای مناسب است.",
|
||||
"summary": "برای پشتیبانی از گلدهی و کاهش تنش تغذیه ای پیشنهاد می شود.",
|
||||
},
|
||||
"nutrient_analysis": {
|
||||
"macro": [
|
||||
{
|
||||
"key": "n",
|
||||
"name": "نیتروژن (N)",
|
||||
"value": 15,
|
||||
"unit": "percent",
|
||||
"description": "نیتروژن برای حفظ رشد رویشی مهم است.",
|
||||
}
|
||||
],
|
||||
"micro": [],
|
||||
},
|
||||
"application_guide": {
|
||||
"safety_warning": "در ساعات خنک مصرف شود و از اختلاط ناسازگار خودداری کنید.",
|
||||
"steps": [
|
||||
{"step_number": 1, "title": "آماده سازی", "description": "دوز را آماده کنید."},
|
||||
{"step_number": 2, "title": "تزریق یا پخش", "description": "طبق روش مصرف اجرا کنید."},
|
||||
{"step_number": 3, "title": "پایش", "description": "پاسخ مزرعه را بررسی کنید."},
|
||||
],
|
||||
},
|
||||
"alternative_recommendations": [],
|
||||
},
|
||||
},
|
||||
response_only=True,
|
||||
),
|
||||
],
|
||||
)
|
||||
def post(self, request):
|
||||
@@ -81,17 +124,14 @@ class FertilizationRecommendView(APIView):
|
||||
)
|
||||
|
||||
validated = serializer.validated_data
|
||||
farm_uuid = validated["farm_uuid"]
|
||||
plant_name = validated.get("plant_name")
|
||||
growth_stage = validated.get("growth_stage")
|
||||
query = validated.get("query")
|
||||
|
||||
try:
|
||||
result = get_fertilization_recommendation(
|
||||
farm_uuid=farm_uuid,
|
||||
plant_name=plant_name,
|
||||
growth_stage=growth_stage,
|
||||
query=query,
|
||||
farm_uuid=validated["farm_uuid"],
|
||||
plant_name=validated.get("plant_name"),
|
||||
crop_id=validated.get("crop_id"),
|
||||
growth_stage=validated.get("growth_stage"),
|
||||
query=validated.get("query"),
|
||||
)
|
||||
except Exception as exc:
|
||||
return Response(
|
||||
@@ -99,8 +139,10 @@ class FertilizationRecommendView(APIView):
|
||||
status=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
)
|
||||
|
||||
# Public API exposes only the final farmer-facing recommendation object.
|
||||
final_result = {"sections": result.get("sections", [])}
|
||||
final_result = result.get("data") if isinstance(result, dict) else None
|
||||
if not isinstance(final_result, dict):
|
||||
final_result = {"sections": result.get("sections", [])} if isinstance(result, dict) else {}
|
||||
|
||||
return Response(
|
||||
{"code": 200, "msg": "success", "data": final_result},
|
||||
status=status.HTTP_200_OK,
|
||||
|
||||
Reference in New Issue
Block a user