Files
Backend/API_DATA_SOURCE_AUDIT_FA.md
T

329 lines
17 KiB
Markdown
Raw Normal View History

2026-04-27 00:40:59 +03:30
# گزارش بررسی منبع داده APIها
تاریخ بررسی: 2026-04-26
## جمع‌بندی خیلی کوتاه
z
- در این repo، بیشتر endpointهایی که `external_api_request("ai", ...)` صدا می‌زنند **از mock داخلی این backend استفاده نمی‌کنند** و به‌صورت HTTP به سرویس AI می‌روند.
- دلیلش این است که در `external_api_adapter/adapter.py` شرط mock این‌طور نوشته شده: `USE_EXTERNAL_API_MOCK and service_name != "ai"`.
- در `.env` فعلی، `USE_EXTERNAL_API_MOCK=true` است، اما چون سرویس این endpointها `ai` است، باز هم درخواست‌ها به سرویس واقعیِ تنظیم‌شده در `AI_SERVICE_BASE_URL=http://ai-web:8000` می‌روند.
- پس برای endpointهای proxy شده به `ai`، از نگاه این backend، **منبع فعلی داده = سرویس واقعی AI** است، نه فایل‌های mock همین repo.
- بعضی endpointها اصلاً external call ندارند و فقط از `mock_data.py` یا از دیتابیس خود Django استفاده می‌کنند.
## مبنای تشخیص
### تنظیمات سراسری
- `USE_EXTERNAL_API_MOCK=true`
- `AI_SERVICE_BASE_URL=http://ai-web:8000`
- `AI_SERVICE_HOST_HEADER=localhost`
### رفتار adapter
در `external_api_adapter/adapter.py`:
```python
use_mock = getattr(settings, "USE_EXTERNAL_API_MOCK", False) and service_name != "ai"
```
یعنی:
- برای `farm_hub` و سرویس‌های غیر `ai` امکان mock داخلی هست.
- برای `ai` **حتی اگر** `USE_EXTERNAL_API_MOCK=true` باشد، درخواست mock نمی‌شود و مستقیم HTTP call زده می‌شود.
> نکته: این گزارش فقط نشان می‌دهد این backend داده را از کجا می‌گیرد. اینکه خود سرویس `ai-web:8000` پشت صحنه mock برگرداند یا داده واقعی تولید کند، از داخل این repo قابل اثبات نیست.
---
## 1) Pest Detection
| Endpoint | منبع داده فعلی | نوع داده فعلی | آدرس/منبع دقیق |
|---|---|---|---|
| `POST /api/pest-detection/analyze/` | سرویس AI خارجی | واقعی از دید backend | `http://ai-web:8000/api/pest-detection/analyze/` |
| `POST /api/pest-detection/risk/` | سرویس AI خارجی | واقعی از دید backend | `http://ai-web:8000/api/pest-detection/risk/` |
| `GET /api/pest-detection/risk-summary/` | سرویس AI خارجی | واقعی از دید backend | `http://ai-web:8000/api/pest-detection/risk-summary/` |
### توضیح
- هر 3 endpoint در `pest_detection/views.py` مستقیم `external_api_request("ai", ...)` صدا می‌زنند.
- فایل `pest_detection/services.py` یک mock به نام `get_risk_summary_data` دارد، ولی **در endpoint واقعی `risk-summary` استفاده نمی‌شود**.
- نتیجه: در وضعیت فعلی این 3 endpoint **mock محلی backend نیستند**.
---
## 2) Plant Simulator
| Endpoint | منبع داده فعلی | نوع داده فعلی | آدرس/منبع دقیق |
|---|---|---|---|
| `GET /api/plant-simulator/config/` | `yield_harvest.mock_data.CONFIG_SLIDERS_ONLY` | mock/static | internal |
| `PATCH /api/plant-simulator/environment/` | پاسخ ثابت success | mock/static | internal |
| `POST /api/plant-simulator/reset/` | پاسخ ثابت success | mock/static | internal |
| `POST /api/plant-simulator/start/` | `yield_harvest.mock_data.START_RESPONSE_DATA` | mock/static | internal |
| `GET /api/plant-simulator/state/` | `yield_harvest.mock_data.STATE_RESPONSE_DATA` | mock/static | internal |
| `POST /api/plant-simulator/stop/` | پاسخ ثابت success | mock/static | internal |
### توضیح
- routeهای `plant-simulator` داخل `yield_harvest/views.py` تعریف شده‌اند.
- هیچ‌کدام external API call ندارند.
- همه این endpointها فعلاً **ماک/استاتیک** هستند.
---
## 3) Soil
| Endpoint | منبع داده فعلی | نوع داده فعلی | آدرس/منبع دقیق |
|---|---|---|---|
| `GET /api/soil/anomalies/` | دیتابیس مدل `farm_alerts.AnomalyDetection` در صورت وجود farm و رکورد، وگرنه `soil.mock_data.ANOMALY_DETECTION_CARD` | ترکیبی: DB / mock | internal DB |
| `GET /api/soil/avg-moisture/` | محاسبه از `get_soil_moisture_heatmap_data()` که خودش از mock می‌آید | mock-derived | internal |
| `GET /api/soil/moisture-heatmap/` | سرویس AI خارجی | واقعی از دید backend | `http://ai-web:8000/api/soile/moisture-heatmap/` |
| `GET /api/sensor-7-in-1/sensor-comparison-chart/` | `sensor_7_in_1.services.get_sensor_comparison_chart_data` | sensor 7 in 1 | internal |
| `GET /api/sensor-7-in-1/sensor-radar-chart/` | `sensor_7_in_1.services.get_sensor_radar_chart_data` | sensor 7 in 1 | internal |
| `GET /api/soil/summary/` | سرویس AI خارجی | واقعی از دید backend | `http://ai-web:8000/api/soile/health-summary/` |
### توضیح
- `avg-moisture` داده واقعی sensor یا external API نمی‌خواند؛ فقط از heatmap ماک میانگین می‌گیرد.
- `anomalies` تنها endpoint این گروه است که **می‌تواند** از DB داخلی بخواند.
- `summary` فقط wrapper همین سرویس‌های داخلی است و خودش external call ندارد.
---
## 4) WATER
| Endpoint | منبع داده فعلی | نوع داده فعلی | آدرس/منبع دقیق |
|---|---|---|---|
| `GET /api/water/card/` | سرویس AI خارجی + ذخیره در `water.WeatherForecastLog` | واقعی از دید backend | `http://ai-web:8000/weather-forecast/card` |
| `GET /api/water/need-prediction/` | اگر `farm_uuid` معتبر باشد: سرویس AI خارجی؛ اگر نباشد: داده مشتق‌شده از `irrigation_recommendation.IrrigationRecommendationRequest` یا mock | ترکیبی | `http://ai-web:8000/api/weather/water-need-prediction/` یا internal DB/mock |
| `GET /api/water/stress-index/` | سرویس AI خارجی | واقعی از دید backend | `http://ai-web:8000/api/water/stress-index/` |
| `GET /api/water/summary/` | local aggregation از `WeatherForecastLog` + `IrrigationRecommendationRequest` + mock fallback | ترکیبی | internal DB/mock |
### توضیح
- `water/card` در لحظه درخواست از AI می‌خواند و نتیجه را در `WeatherForecastLog` ذخیره می‌کند.
- `water/need-prediction` رفتار دوحالته دارد:
- اگر `farm_uuid` داده شود و farm پیدا شود: مستقیم به AI می‌رود.
- اگر farm نداشته باشد: از آخرین `IrrigationRecommendationRequest` می‌سازد؛ اگر چیزی نباشد، از `water.mock_data` می‌دهد.
- `water/summary` خودش به AI زنگ نمی‌زند؛ فقط داده cached/local را assemble می‌کند.
---
## 5) WEATHER
| Endpoint | منبع داده فعلی | نوع داده فعلی | آدرس/منبع دقیق |
|---|---|---|---|
| `POST /api/weather/farm-card/` | سرویس AI خارجی + ذخیره در `WeatherForecastLog` | واقعی از دید backend | `http://ai-web:8000/weather-forecast/card` |
### توضیح
- در namespace `weather` فقط `POST /api/weather/farm-card/` باقی مانده است.
- endpoint `POST /api/weather/water-need-prediction/` حذف شده است.
---
## 6) Yield & Harvest Prediction
| Endpoint | منبع داده فعلی | نوع داده فعلی | آدرس/منبع دقیق |
|---|---|---|---|
| `GET /api/yield-harvest/summary/` | سرویس AI خارجی + ذخیره در `yield_harvest.YieldHarvestPredictionLog` | واقعی از دید backend | `http://ai-web:8000/yield-harvest/summary` |
### توضیح
- این endpoint در `yield_harvest/views.py` مستقیماً AI را صدا می‌زند.
- سپس نتیجه در `YieldHarvestPredictionLog` ذخیره می‌شود.
- سرویس `yield_harvest/services.py` برای خواندن از log و fallback mock وجود دارد، اما خود endpoint `summary` در حال حاضر **آن سرویس را استفاده نمی‌کند**.
---
## 7) Fertilization Recommendation
| Endpoint | منبع داده فعلی | نوع داده فعلی | آدرس/منبع دقیق |
|---|---|---|---|
| `GET /api/fertilization/config/` | `fertilization_recommendation.mock_data.CONFIG_RESPONSE_DATA` | mock/static | internal |
| `POST /api/fertilization/recommend/` | سرویس AI خارجی + ذخیره در `FertilizationRecommendationRequest` | واقعی از دید backend | `http://ai-web:8000/api/fertilization/recommend/` |
### توضیح
- `config` فعلاً فقط config ثابت برمی‌گرداند.
- `recommend` واقعی از نگاه backend است و پاسخ خام AI در DB ذخیره می‌شود.
---
## 8) Irrigation Recommendation
| Endpoint | منبع داده فعلی | نوع داده فعلی | آدرس/منبع دقیق |
|---|---|---|---|
| `GET /api/irrigation/` | سرویس AI خارجی | واقعی از دید backend | `http://ai-web:8000/api/irrigation/` |
| `GET /api/irrigation/config/` | `irrigation_recommendation.mock_data.CONFIG_RESPONSE_DATA` | mock/static | internal |
| `POST /api/irrigation/recommend/` | سرویس AI خارجی + ذخیره در `IrrigationRecommendationRequest` | واقعی از دید backend | `http://ai-web:8000/api/irrigation/recommend/` |
### نکته مهم درباره مسیر درخواستی شما
مسیر `POST /api/irrigation/water-stress/farm-alerts` در این backend **وجود ندارد**.
مسیرهای نزدیک و واقعی این‌ها هستند:
- `POST /api/irrigation/water-stress/`
- منبع فعلی: سرویس AI خارجی
- آدرس upstream: `http://ai-web:8000/api/water/stress-index/`
- endpointهای `farm-alerts` جدا هستند و زیر prefix دیگری قرار دارند:
- `/api/farm-alerts/...`
---
## 9) Farm Alerts
| Endpoint | منبع داده فعلی | نوع داده فعلی | آدرس/منبع دقیق |
|---|---|---|---|
| `GET /api/farm-alerts/anomalies/` | `farm_alerts.mock_data.ANOMALY_DETECTION_CARD` | mock/static | internal |
| `POST /api/farm-alerts/create/` | دیتابیس داخلی (`FarmAlert`) + ساخت `FarmNotification` | internal DB | internal DB |
| `GET /api/farm-alerts/recommendations/` | `farm_alerts.mock_data.RECOMMENDATIONS_LIST` | mock/static | internal |
| `GET /api/farm-alerts/timeline/` | `farm_alerts.mock_data.FARM_ALERTS_TIMELINE` | mock/static | internal |
### نکته مهم درباره مسیر درخواستی شما
مسیر `GET /api/farm-alerts/tracker/economy` در این backend **وجود ندارد**.
مسیر درست موجود:
- `GET /api/farm-alerts/tracker/`
- منبع فعلی: `farm_alerts.mock_data.ARM_ALERTS_TRACKER`
- نوع: mock/static
### توضیح
- با اینکه در `farm_alerts/services.py` توابعی برای خواندن tracker/timeline/anomalies/recommendations از DB وجود دارد، viewهای فعلی از آن‌ها استفاده نمی‌کنند.
- بنابراین در وضعیت فعلی:
- `tracker` = mock
- `timeline` = mock
- `anomalies` = mock
- `recommendations` = mock
- فقط `create` واقعاً به DB داخلی می‌نویسد.
---
## 10) Economy
| Endpoint | منبع داده فعلی | نوع داده فعلی | آدرس/منبع دقیق |
|---|---|---|---|
| `POST /api/economy/overview/` | سرویس AI خارجی + ذخیره در `economic_overview.EconomicOverviewLog` | واقعی از دید backend | `http://ai-web:8000/api/economy/overview/` |
### توضیح
- endpoint تکراری `GET /api/economy/summary/` حذف شده است.
- endpoint canonical اقتصادی فقط این است:
- `POST /api/economy/overview/`
- این endpoint داده را از AI می‌گیرد و در `EconomicOverviewLog` ذخیره می‌کند.
---
## 11) Crop Health
| Endpoint | منبع داده فعلی | نوع داده فعلی | آدرس/منبع دقیق |
|---|---|---|---|
| `POST /api/crop-health/ndvi-health/` | `crop_health.mock_data.NDVI_HEALTH_CARD` | mock/static | internal |
| `GET /api/crop-health/summary/` | `crop_health.mock_data.NDVI_HEALTH_CARD` + `crop_health.mock_data.FARM_HEALTH_SCORE` | mock/static | internal |
### توضیح
- `get_crop_health_summary_data(farm=None)` در `crop_health/services.py` پارامتر farm را نادیده می‌گیرد.
- پس حتی نسخه POST که farm را validate می‌کند هم در نهایت داده mock برمی‌گرداند.
---
## 12) Soil Data
| Endpoint | منبع داده فعلی | نوع داده فعلی | آدرس/منبع دقیق |
|---|---|---|---|
| `POST /api/soil/health/ndvi-health/` | همان `crop_health` | mock/static | internal |
| `GET /api/soil/health/summary/` | همان `crop_health` | mock/static | internal |
### توضیح
- در `config/urls.py` مسیرهای `crop_health` زیر `api/soil/health/` هم mount شده‌اند.
- یعنی این دو endpoint عملاً alias همان endpointهای `crop-health` هستند.
- بنابراین هر دو فعلاً **mock/static** هستند.
---
## 13) Crop Simulation
| Endpoint | منبع داده فعلی | نوع داده فعلی | آدرس/منبع دقیق |
|---|---|---|---|
| `POST /api/yield-harvest/crop-simulation/current-farm-chart/` | سرویس AI خارجی | واقعی از دید backend | `http://ai-web:8000/api/crop-simulation/current-farm-chart/` |
| `POST /api/yield-harvest/crop-simulation/harvest-prediction/` | سرویس AI خارجی | واقعی از دید backend | `http://ai-web:8000/api/crop-simulation/harvest-prediction/` |
| `POST /api/yield-harvest/crop-simulation/yield-prediction/` | سرویس AI خارجی | واقعی از دید backend | `http://ai-web:8000/api/crop-simulation/yield-prediction/` |
### توضیح
- هر سه endpoint در `yield_harvest/views.py` هستند.
- هر سه مستقیماً `external_api_request("ai", ...)` صدا می‌زنند.
---
## جدول نهایی وضعیت فعلی
### endpointهایی که الان از سرویس AI می‌گیرند
- `POST /api/pest-detection/analyze/`
- `POST /api/pest-detection/risk/`
- `GET /api/pest-detection/risk-summary/`
- `GET /api/water/card/`
- `GET /api/water/stress-index/`
- `POST /api/weather/farm-card/`
- `GET /api/yield-harvest/summary/`
- `POST /api/fertilization/recommend/`
- `GET /api/irrigation/`
- `POST /api/irrigation/recommend/`
- `POST /api/irrigation/water-stress/`
- `POST /api/yield-harvest/crop-simulation/current-farm-chart/`
- `POST /api/yield-harvest/crop-simulation/harvest-prediction/`
- `POST /api/yield-harvest/crop-simulation/yield-prediction/`
### endpointهایی که الان mock/static هستند
- همه `plant-simulator`
- `GET /api/soil/moisture-heatmap/`
- `GET /api/sensor-7-in-1/sensor-comparison-chart/`
- `GET /api/sensor-7-in-1/sensor-radar-chart/`
- `GET /api/fertilization/config/`
- `GET /api/irrigation/config/`
- `GET /api/farm-alerts/tracker/`
- `GET /api/farm-alerts/timeline/`
- `GET /api/farm-alerts/anomalies/`
- `GET /api/farm-alerts/recommendations/`
- `POST /api/economy/overview/`
- `POST /api/crop-health/ndvi-health/`
- `GET /api/crop-health/summary/`
- `POST /api/soil/health/ndvi-health/`
- `GET /api/soil/health/summary/`
### endpointهایی که ترکیبی هستند
- `GET /api/soil/anomalies/` → DB اگر data باشد، وگرنه mock
- `GET /api/soil/avg-moisture/` → derived from mock heatmap
- `GET /api/soil/summary/` → سرویس AI خارجی
- `GET /api/water/need-prediction/` → با `farm_uuid` معتبر معمولاً AI، بدون آن local/mock
- `GET /api/water/summary/` → local DB/cache/mock
### مسیرهایی که در این backend وجود ندارند
- `POST /api/irrigation/water-stress/farm-alerts`
- `GET /api/farm-alerts/tracker/economy`
---
## پیشنهاد برای اصلاح اگر هدف شما «داده واقعی» است
اگر بخواهید این endpointها واقعاً از داده واقعی backend خودشان بخوانند، اولویت اصلاح منطقی این‌هاست:
1. `farm_alerts/views.py`
- به‌جای mock مستقیم، از توابع `farm_alerts/services.py` استفاده شود.
2. `economic_overview/views.py`
- `summary` از `get_economic_overview_data()` استفاده کند، نه mock ثابت.
3. `crop_health/services.py`
- به‌جای mock ثابت، از منبع واقعی NDVI یا cache/database استفاده کند.
4. `soil/services.py`
- heatmap/radar/comparison از sensor logs واقعی ساخته شوند.
5. `water/summary`
- در صورت نیاز، به‌جای cache/log فقط، امکان refresh مستقیم از AI داشته باشد.