# ساختار فعلی `location_data`

این فایل وضعیت فعلی اپ `location_data` را توضیح می‌دهد؛ هم از نظر ساختار فایل‌ها و هم از نظر مدل‌ها، APIها و جریان داده.

## هدف فعلی اپ

اپ `location_data` فعلاً این مسئولیت‌ها را دارد:

- نگه‌داری موقعیت زمین با `lat` و `lon`
- نگه‌داری مرز مزرعه در `farm_boundary`
- نگه‌داری ساختار بلوک‌های زمین در `block_layout`
- نگه‌داری داده‌های خاک برای عمق‌های مختلف در `SoilDepthData`
- نگه‌داری مشاهدات NDVI در `NdviObservation`
- برگرداندن ساختار بلوک‌های زمین از API محلی بدون نیاز به API خارجی در فاز فعلی

نکته مهم:

- در فاز فعلی، endpoint اصلی `location_data` برای ساختار زمین، فقط داده را در دیتابیس می‌خواند/ذخیره می‌کند.
- فعلاً برای بلوک‌ها، زیر‌بلوک‌ها و داده‌های ماهواره‌ای هیچ درخواست خارجی زده نمی‌شود.

## ساختار فایل‌ها

```text
location_data/
├── admin.py
├── apps.py
├── models.py
├── serializers.py
├── views.py
├── urls.py
├── tasks.py
├── soil_adapters.py
├── remote_sensing.py
├── ndvi.py
├── test_soil_api.py
├── test_soil_adapters.py
├── test_ndvi_health_api.py
├── postman/
│   └── soil_data.json
├── management/
│   └── commands/
└── migrations/
    ├── 0001_initial.py
    ├── 0002_soildepthdata_refactor.py
    ├── 0002_soillocation_ideal_sensor_profile.py
    ├── 0003_rename_app_label.py
    ├── 0004_soillocation_farm_boundary.py
    ├── 0005_merge_20260327_0840.py
    ├── 0006_remove_soillocation_ideal_sensor_profile.py
    ├── 0007_ndviobservation.py
    └── 0008_soillocation_block_layout.py
```

## مدل‌ها و جدول‌ها

### 1) `SoilLocation`

مدل اصلی اپ است و نماینده یک موقعیت یکتا برای زمین یا مرکز زمین محسوب می‌شود.

فیلدهای اصلی:

| فیلد | نوع | توضیح |
|---|---|---|
| `id` | `BigAutoField` | شناسه داخلی رکورد |
| `latitude` | `DecimalField(9,6)` | عرض جغرافیایی |
| `longitude` | `DecimalField(9,6)` | طول جغرافیایی |
| `task_id` | `CharField` | شناسه تسک Celery برای جریان قدیمی واکشی خاک |
| `farm_boundary` | `JSONField` | مرز مزرعه به شکل Polygon یا corners |
| `input_block_count` | `PositiveIntegerField` | تعداد بلوک اولیه‌ای که از ورودی کشاورز می‌آید |
| `block_layout` | `JSONField` | ساختار بلوک‌ها و زیر‌بلوک‌های زمین |
| `created_at` | `DateTimeField` | زمان ایجاد |
| `updated_at` | `DateTimeField` | زمان آخرین تغییر |

قیدها:

- روی ترکیب `latitude` و `longitude` یکتا است.

رفتار مهم:

- اگر `input_block_count` ارسال نشود، مقدار پیش‌فرض `1` است.
- اگر `block_layout` خالی باشد، به صورت خودکار با یک بلوک کامل ساخته می‌شود.
- متد `set_input_block_count()` ساختار اولیه بلوک‌ها را می‌سازد.

### 2) `SoilDepthData`

این مدل داده‌های خاک را برای هر عمق نگه می‌دارد و به `SoilLocation` وصل است.

عمق‌های فعلی:

- `0-5cm`
- `5-15cm`
- `15-30cm`

فیلدهای مهم:

| فیلد | نوع | توضیح |
|---|---|---|
| `soil_location` | `ForeignKey` | ارتباط با `SoilLocation` |
| `depth_label` | `CharField` | برچسب عمق |
| `bdod` تا `wv1500` | `FloatField` | پارامترهای مختلف خاک |
| `created_at` | `DateTimeField` | زمان ثبت رکورد |

قیدها:

- برای هر `soil_location` و هر `depth_label` فقط یک رکورد وجود دارد.

### 3) `NdviObservation`

این مدل برای ذخیره مشاهده‌های NDVI استفاده می‌شود.

فیلدهای مهم:

| فیلد | نوع | توضیح |
|---|---|---|
| `location` | `ForeignKey` | ارتباط با `SoilLocation` |
| `observation_date` | `DateField` | تاریخ مشاهده |
| `mean_ndvi` | `FloatField` | میانگین NDVI |
| `ndvi_map` | `JSONField` | داده مکانی NDVI |
| `vegetation_health_class` | `CharField` | کلاس سلامت پوشش گیاهی |
| `satellite_source` | `CharField` | منبع تصویر ماهواره‌ای |
| `cloud_cover` | `FloatField` | درصد ابر |
| `metadata` | `JSONField` | داده تکمیلی |

## ساختار `block_layout`

فیلد `block_layout` فعلاً ساختار پایه تقسیم زمین را نگه می‌دارد.

نمونه پیش‌فرض وقتی کل زمین یک بلوک باشد:

```json
{
  "input_block_count": 1,
  "default_full_farm": true,
  "algorithm_status": "pending",
  "blocks": [
    {
      "block_code": "block-1",
      "order": 1,
      "source": "default",
      "needs_subdivision": null,
      "sub_blocks": []
    }
  ]
}
```

نمونه وقتی ورودی مثلاً `block_count = 3` باشد:

```json
{
  "input_block_count": 3,
  "default_full_farm": false,
  "algorithm_status": "pending",
  "blocks": [
    {
      "block_code": "block-1",
      "order": 1,
      "source": "input",
      "needs_subdivision": null,
      "sub_blocks": []
    },
    {
      "block_code": "block-2",
      "order": 2,
      "source": "input",
      "needs_subdivision": null,
      "sub_blocks": []
    },
    {
      "block_code": "block-3",
      "order": 3,
      "source": "input",
      "needs_subdivision": null,
      "sub_blocks": []
    }
  ]
}
```

معنای فیلدها:

| فیلد | توضیح |
|---|---|
| `input_block_count` | تعداد بلوک اولیه |
| `default_full_farm` | آیا کل زمین هنوز یک بلوک کامل است یا نه |
| `algorithm_status` | وضعیت اجرای الگوریتم تقسیم‌بندی |
| `blocks` | لیست بلوک‌های فعلی |
| `block_code` | کد بلوک |
| `order` | ترتیب بلوک |
| `source` | منشأ بلوک: `default` یا `input` |
| `needs_subdivision` | آیا الگوریتم تشخیص داده که این بلوک باید خردتر شود یا نه |
| `sub_blocks` | لیست زیر‌بلوک‌ها |

## Serializerها

### `SoilDataRequestSerializer`

ورودی endpoint اصلی `location_data`:

| فیلد | اجباری | توضیح |
|---|---|---|
| `lat` | بله | عرض جغرافیایی |
| `lon` | بله | طول جغرافیایی |
| `block_count` | خیر | تعداد بلوک اولیه، پیش‌فرض `1` |

### `SoilLocationResponseSerializer`

خروجی اصلی برای یک location:

- `id`
- `lat`
- `lon`
- `input_block_count`
- `block_layout`
- `depths`

### `SoilDepthDataSerializer`

لیست پارامترهای خاک برای هر عمق را برمی‌گرداند.

### `NdviHealthRequestSerializer` و `NdviHealthResponseSerializer`

برای endpoint مربوط به NDVI استفاده می‌شوند.

## Viewها و APIها

### 1) `SoilDataView`

مسیر:

- `GET /api/soil-data/`
- `POST /api/soil-data/`

وظیفه فعلی:

- گرفتن `lat` و `lon`
- گرفتن `block_count` در صورت وجود
- ساخت یا پیدا کردن `SoilLocation`
- ذخیره `input_block_count`
- ساخت `block_layout`
- برگرداندن پاسخ با `source = local`

رفتار فعلی:

- اگر location وجود نداشته باشد، ساخته می‌شود.
- اگر `block_count` تغییر کند، ساختار `block_layout` دوباره ساخته می‌شود.
- فعلاً هیچ fetch خارجی برای اطلاعات خاک یا ماهواره‌ای انجام نمی‌شود.

### 2) `SoilDataTaskStatusView`

مسیر:

- `GET /api/soil-data/tasks/<task_id>/status/`

وضعیت فعلی:

- هنوز در کد وجود دارد.
- برای جریان قدیمی مبتنی بر Celery طراحی شده است.
- با تغییر اخیر، endpoint اصلی `location_data` دیگر به‌طور پیش‌فرض task جدیدی صف نمی‌کند.

### 3) `NdviHealthView`

مسیر:

- `POST /api/soil-data/ndvi-health/`

وظیفه:

- دریافت `farm_uuid`
- خواندن داده NDVI از سرویس داخلی NDVI
- برگرداندن اطلاعات سلامت پوشش گیاهی

## فایل `tasks.py`

این فایل هنوز منطق قدیمی واکشی داده خاک را نگه می‌دارد.

اجزای اصلی:

- `fetch_soil_data_for_coordinates()`
- `fetch_soil_data_task()`

نکته:

- این بخش هنوز برای سازگاری و جریان‌های قدیمی در پروژه باقی مانده است.
- ولی در فاز فعلی تقسیم بلوک‌ها، از این task برای endpoint اصلی `location_data` استفاده نمی‌شود.

## فایل `soil_adapters.py`

این فایل abstraction مربوط به تامین داده خاک را نگه می‌دارد.

کاربرد آن:

- mock provider
- live soil provider
- ساختار depth-based data fetch

در وضعیت فعلی:

- برای منطق بلوک‌بندی فعلی لازم نیست.
- اما برای جریان قدیمی یا مراحل بعدی می‌تواند دوباره استفاده شود.

## فایل `remote_sensing.py`

این فایل مربوط به منطق سنجش‌ازدور و داده‌های ماهواره‌ای است.

در وضعیت فعلی:

- برای block layout فعلاً استفاده فعال ندارد.
- بعداً می‌تواند برای تحلیل هر بلوک یا زیر‌بلوک استفاده شود.

## فایل `ndvi.py`

این فایل سرویس/منطق NDVI را نگه می‌دارد و برای endpoint NDVI استفاده می‌شود.

## migrationها

مهم‌ترین migrationهای فعلی:

| migration | توضیح |
|---|---|
| `0001_initial.py` | ساختار اولیه `SoilLocation` |
| `0002_soildepthdata_refactor.py` | جداسازی داده‌های عمقی در `SoilDepthData` |
| `0004_soillocation_farm_boundary.py` | اضافه شدن `farm_boundary` |
| `0007_ndviobservation.py` | اضافه شدن `NdviObservation` |
| `0008_soillocation_block_layout.py` | اضافه شدن `input_block_count` و `block_layout` |

## تست‌ها

فایل‌های تست اصلی:

- `location_data/test_soil_api.py`
  - تست ساختار محلی بلوک‌ها
  - تست پیش‌فرض یک بلوک
  - تست تغییر `block_count`

- `location_data/test_soil_adapters.py`
  - تست adapterهای خاک
  - تست ذخیره depth data

- `location_data/test_ndvi_health_api.py`
  - تست endpoint NDVI

## ارتباط با `farm_data`

`location_data` مستقیماً توسط `farm_data` استفاده می‌شود.

نمونه وابستگی‌ها:

- `farm_data` از `SoilLocation` به عنوان `center_location` استفاده می‌کند.
- `farm_boundary` از سمت `farm_data` می‌آید.
- `block_count` هم از ورودی `farm_data` قابل ثبت است.
- `farm_data` فعلاً فقط location و block layout را ذخیره می‌کند و برای این بخش sync خارجی انجام نمی‌دهد.

## جمع‌بندی ساختار فعلی

الان `location_data` دو لایه دارد:

1. لایه فعلی فعال برای بلوک‌بندی زمین
   - محلی
   - ساده
   - بدون API خارجی
   - با `input_block_count` و `block_layout`

2. لایه قدیمی/جانبی برای خاک و NDVI
   - `SoilDepthData`
   - `tasks.py`
   - `soil_adapters.py`
   - `NdviObservation`
   - `remote_sensing.py`

یعنی از نظر معماری، اپ الان هم داده مکانی زمین را نگه می‌دارد و هم زیرساختی برای تحلیل خاک/NDVI دارد، ولی منطق جدید بلوک‌ها فعلاً مستقل و محلی پیاده شده است.
