# Free-Text Plan Parser APIs

این فایل برای تیم فرانت‌اند آماده شده و دو API جدید زیر را توضیح می‌دهد:

- `POST /api/irrigation/plan-from-text/`
- `POST /api/fertilization/plan-from-text/`

هدف هر دو API:

- کاربر یک متن آزاد می‌نویسد
- بک‌اند تلاش می‌کند برنامه آبیاری یا کودهی را به JSON ساختاریافته تبدیل کند
- اگر اطلاعات کامل باشد، JSON نهایی برمی‌گردد
- اگر اطلاعات ناقص باشد، API سوال‌های تکمیلی برمی‌گرداند
- فرانت‌اند سوال‌ها را از کاربر می‌پرسد و پاسخ‌ها را دوباره برای API می‌فرستد

---

## رفتار کلی هر دو API

هر دو endpoint یک flow یکسان دارند:

1. کاربر متن آزاد اولیه را می‌فرستد
2. اگر متن کامل باشد:
   - `status = "completed"`
   - `final_plan` برمی‌گردد
3. اگر متن ناقص باشد:
   - `status = "needs_clarification"`
   - `missing_fields` برمی‌گردد
   - `questions` برمی‌گردد
4. فرانت‌اند پاسخ کاربر به سوال‌ها را جمع می‌کند
5. دوباره همان endpoint را با `answers` و `partial_plan` صدا می‌زند
6. این روند تا ساخته شدن `final_plan` ادامه پیدا می‌کند

---

## الگوی کلی response

هر دو API از envelope استاندارد استفاده می‌کنند:

```json
{
  "code": 200,
  "msg": "موفق",
  "data": {}
}
```

### معنی فیلدهای envelope

| فیلد | نوع | توضیح |
|---|---|---|
| `code` | number | کد منطقی پاسخ |
| `msg` | string | پیام کوتاه پاسخ |
| `data` | object | داده اصلی API |

---

## 1) API استخراج برنامه آبیاری

### Endpoint

```http
POST /api/irrigation/plan-from-text/
```

### کاربرد

این API متن آزاد کاربر درباره برنامه آبیاری را به JSON ساختاریافته تبدیل می‌کند.

### Request Body

هر سه فیلد زیر اختیاری هستند، اما حداقل یکی از این‌ها باید ارسال شود:

- `message`
- `answers`
- `partial_plan`

#### ساختار request

```json
{
  "message": "برای گوجه فرنگی با آبیاری قطره ای هر سه روز یک بار صبح زود 25 دقیقه آبیاری می کنم و حدود 18 لیتر برای هر بوته می دهم.",
  "answers": {
    "growth_stage": "گلدهی"
  },
  "partial_plan": {
    "crop_name": "گوجه فرنگی",
    "irrigation_method": "قطره ای"
  },
  "farm_uuid": "11111111-1111-1111-1111-111111111111"
}
```

### فیلدهای request

| فیلد | نوع | اجباری | توضیح |
|---|---|---:|---|
| `message` | string | خیر | متن آزاد کاربر |
| `answers` | object | خیر | پاسخ‌های تکمیلی کاربر به سوال‌هایی که قبلا API داده |
| `partial_plan` | object | خیر | خروجی مرحله قبل برای ادامه تکمیل |
| `farm_uuid` | string | خیر | برای غنی‌سازی context مزرعه در RAG |

### قانون validation

اگر هیچ‌کدام از `message`، `answers` یا `partial_plan` ارسال نشوند:

```json
{
  "code": 400,
  "msg": "داده نامعتبر.",
  "data": {
    "non_field_errors": [
      "حداقل یکی از message، answers یا partial_plan باید ارسال شود."
    ]
  }
}
```

---

## پاسخ موفق - حالت تکمیل شده

وقتی همه اطلاعات لازم موجود باشد:

```json
{
  "code": 200,
  "msg": "موفق",
  "data": {
    "status": "completed",
    "status_fa": "تکمیل شد",
    "summary": "برنامه آبیاری برای گوجه‌فرنگی به روش قطره‌ای هر سه روز یک‌بار صبح زود به مدت 25 دقیقه اجرا می‌شود.",
    "missing_fields": [],
    "questions": [],
    "collected_data": {
      "crop_name": "گوجه‌فرنگی",
      "growth_stage": "گلدهی",
      "irrigation_method": "قطره‌ای",
      "water_amount_per_event": "18 لیتر برای هر بوته",
      "duration_minutes": 25,
      "frequency_text": "هر سه روز یک‌بار",
      "interval_days": 3,
      "preferred_time_of_day": "صبح زود",
      "start_date": "از امروز",
      "target_area": "کل مزرعه",
      "trigger_conditions": [],
      "notes": []
    },
    "final_plan": {
      "crop_name": "گوجه‌فرنگی",
      "growth_stage": "گلدهی",
      "irrigation_method": "قطره‌ای",
      "water_amount_per_event": "18 لیتر برای هر بوته",
      "duration_minutes": 25,
      "frequency_text": "هر سه روز یک‌بار",
      "interval_days": 3,
      "preferred_time_of_day": "صبح زود",
      "start_date": "از امروز",
      "target_area": "کل مزرعه",
      "trigger_conditions": [],
      "notes": []
    }
  }
}
```

### فیلدهای `data`

| فیلد | نوع | توضیح |
|---|---|---|
| `status` | string | یکی از `completed` یا `needs_clarification` |
| `status_fa` | string | نسخه فارسی وضعیت |
| `summary` | string | خلاصه قابل نمایش برای کاربر |
| `missing_fields` | array[string] | فیلدهای ناقص |
| `questions` | array[object] | سوال‌های تکمیلی |
| `collected_data` | object | داده‌ای که تا الان از متن و جواب‌ها استخراج شده |
| `final_plan` | object/null | برنامه نهایی؛ فقط در حالت `completed` |

### فیلدهای `collected_data` و `final_plan`

| فیلد | نوع | توضیح |
|---|---|---|
| `crop_name` | string | نام محصول |
| `growth_stage` | string | مرحله رشد محصول |
| `irrigation_method` | string | روش آبیاری |
| `water_amount_per_event` | string | مقدار آب هر نوبت |
| `duration_minutes` | number | مدت هر نوبت آبیاری به دقیقه |
| `frequency_text` | string | توصیف متنی فاصله آبیاری |
| `interval_days` | number | فاصله آبیاری بر حسب روز |
| `preferred_time_of_day` | string | زمان مناسب اجرای آبیاری |
| `start_date` | string | زمان یا تاریخ شروع برنامه |
| `target_area` | string | محدوده هدف برنامه |
| `trigger_conditions` | array[string] | شرایط تریگر اختیاری |
| `notes` | array[string] | نکات تکمیلی |

---

## پاسخ موفق - حالت نیاز به سوال تکمیلی

اگر اطلاعات کامل نباشد:

```json
{
  "code": 200,
  "msg": "موفق",
  "data": {
    "status": "needs_clarification",
    "status_fa": "نیازمند پرسش تکمیلی",
    "summary": "اطلاعات برنامه آبیاری برای ساخت JSON نهایی کافی نیست و به چند پاسخ تکمیلی نیاز است.",
    "missing_fields": [
      "growth_stage",
      "start_date",
      "target_area"
    ],
    "questions": [
      {
        "id": "growth_stage",
        "field": "growth_stage",
        "question": "محصول الان در چه مرحله رشدی قرار دارد؟",
        "rationale": "مرحله رشد برای کامل شدن برنامه لازم است."
      },
      {
        "id": "start_date",
        "field": "start_date",
        "question": "این برنامه از چه تاریخی یا از چه زمانی باید شروع شود؟",
        "rationale": "زمان شروع برنامه هنوز مشخص نشده است."
      },
      {
        "id": "target_area",
        "field": "target_area",
        "question": "این برنامه برای کل مزرعه است یا بخش/ناحیه خاصی از مزرعه؟",
        "rationale": "محدوده اجرای برنامه باید مشخص باشد."
      }
    ],
    "collected_data": {
      "crop_name": "گوجه‌فرنگی",
      "growth_stage": null,
      "irrigation_method": "قطره‌ای",
      "water_amount_per_event": "18 لیتر برای هر بوته",
      "duration_minutes": 25,
      "frequency_text": "هر سه روز یک‌بار",
      "interval_days": 3,
      "preferred_time_of_day": "صبح زود",
      "start_date": null,
      "target_area": null,
      "trigger_conditions": [],
      "notes": []
    },
    "final_plan": null
  }
}
```

### ساختار `questions`

| فیلد | نوع | توضیح |
|---|---|---|
| `id` | string | شناسه سوال |
| `field` | string | فیلدی که این سوال برای آن پرسیده شده |
| `question` | string | متن سوال برای نمایش به کاربر |
| `rationale` | string | توضیح کوتاه برای اینکه چرا این سوال لازم است |

---

## flow پیشنهادی فرانت‌اند برای آبیاری

### مرحله 1

کاربر متن آزاد می‌فرستد:

```json
{
  "message": "برای گوجه فرنگی هر سه روز یک بار آبیاری می کنم."
}
```

### مرحله 2

اگر `status = needs_clarification` بود:

- سوال‌ها را از `data.questions` به کاربر نمایش بده
- پاسخ‌ها را جمع کن

### مرحله 3

درخواست تکمیلی بزن:

```json
{
  "partial_plan": {
    "crop_name": "گوجه فرنگی",
    "growth_stage": null,
    "irrigation_method": null,
    "water_amount_per_event": null,
    "duration_minutes": null,
    "frequency_text": "هر سه روز یک بار",
    "interval_days": 3,
    "preferred_time_of_day": null,
    "start_date": null,
    "target_area": null,
    "trigger_conditions": [],
    "notes": []
  },
  "answers": {
    "growth_stage": "گلدهی",
    "irrigation_method": "قطره ای",
    "water_amount_per_event": "18 لیتر برای هر بوته",
    "duration_minutes": 25,
    "preferred_time_of_day": "صبح زود",
    "start_date": "از امروز",
    "target_area": "کل مزرعه"
  }
}
```

### مرحله 4

اگر `status = completed` شد:

- از `data.final_plan` به عنوان JSON نهایی استفاده کن

---

## 2) API استخراج برنامه کودهی

### Endpoint

```http
POST /api/fertilization/plan-from-text/
```

### کاربرد

این API متن آزاد کاربر درباره برنامه کودهی را به JSON ساختاریافته تبدیل می‌کند.

### Request Body

```json
{
  "message": "برای گندم در مرحله پنجه زنی هر 12 روز یک بار 20-20-20 به مقدار 35 کیلوگرم در هکتار از طریق کودآبیاری می دهم.",
  "answers": {
    "timing": "هر 12 روز یک بار"
  },
  "partial_plan": {
    "crop_name": "گندم"
  },
  "farm_uuid": "11111111-1111-1111-1111-111111111111"
}
```

### فیلدهای request

| فیلد | نوع | اجباری | توضیح |
|---|---|---:|---|
| `message` | string | خیر | متن آزاد کاربر |
| `answers` | object | خیر | پاسخ‌های تکمیلی کاربر |
| `partial_plan` | object | خیر | داده استخراج شده مرحله قبل |
| `farm_uuid` | string | خیر | برای context مزرعه |

### validation error

```json
{
  "code": 400,
  "msg": "داده نامعتبر.",
  "data": {
    "non_field_errors": [
      "حداقل یکی از message، answers یا partial_plan باید ارسال شود."
    ]
  }
}
```

---

## پاسخ موفق - حالت تکمیل شده

```json
{
  "code": 200,
  "msg": "موفق",
  "data": {
    "status": "completed",
    "status_fa": "تکمیل شد",
    "summary": "برنامه کودهی برای گندم در مرحله پنجه زنی با کود 20-20-20 به صورت کودآبیاری هر 12 روز یک بار اجرا می شود.",
    "missing_fields": [],
    "questions": [],
    "collected_data": {
      "crop_name": "گندم",
      "growth_stage": "پنجه زنی",
      "objective": "تقویت رشد رویشی",
      "applications": [
        {
          "fertilizer_name": "کود کامل 20-20-20",
          "formula": "20-20-20",
          "amount": "35 کیلوگرم در هکتار",
          "application_method": "کودآبیاری",
          "timing": "هر 12 روز یک بار",
          "interval_days": 12,
          "purpose": "تقویت رشد رویشی"
        }
      ],
      "notes": []
    },
    "final_plan": {
      "crop_name": "گندم",
      "growth_stage": "پنجه زنی",
      "objective": "تقویت رشد رویشی",
      "applications": [
        {
          "fertilizer_name": "کود کامل 20-20-20",
          "formula": "20-20-20",
          "amount": "35 کیلوگرم در هکتار",
          "application_method": "کودآبیاری",
          "timing": "هر 12 روز یک بار",
          "interval_days": 12,
          "purpose": "تقویت رشد رویشی"
        }
      ],
      "notes": []
    }
  }
}
```

### فیلدهای `collected_data` و `final_plan`

| فیلد | نوع | توضیح |
|---|---|---|
| `crop_name` | string | نام محصول |
| `growth_stage` | string | مرحله رشد |
| `objective` | string/null | هدف برنامه |
| `applications` | array[object] | لیست نوبت‌ها یا اقلام کودی |
| `notes` | array[string] | نکات تکمیلی |

### ساختار هر application

| فیلد | نوع | توضیح |
|---|---|---|
| `fertilizer_name` | string | نام کود |
| `formula` | string | فرمول یا آنالیز کود |
| `amount` | string | مقدار مصرف |
| `application_method` | string | روش مصرف |
| `timing` | string | زمان‌بندی مصرف |
| `interval_days` | number | فاصله بین نوبت‌ها |
| `purpose` | string/null | هدف آن نوبت |

---

## پاسخ موفق - حالت نیاز به سوال تکمیلی

```json
{
  "code": 200,
  "msg": "موفق",
  "data": {
    "status": "needs_clarification",
    "status_fa": "نیازمند پرسش تکمیلی",
    "summary": "اطلاعات برنامه کودهی برای ساخت JSON نهایی کافی نیست و به چند پاسخ تکمیلی نیاز است.",
    "missing_fields": [
      "growth_stage",
      "formula",
      "interval_days"
    ],
    "questions": [
      {
        "id": "growth_stage",
        "field": "growth_stage",
        "question": "محصول الان در چه مرحله رشدی قرار دارد؟",
        "rationale": "مرحله رشد برای تکمیل برنامه لازم است."
      },
      {
        "id": "formula",
        "field": "formula",
        "question": "فرمول یا آنالیز کود چیست؟ مثلا 20-20-20.",
        "rationale": "ترکیب دقیق کود هنوز مشخص نشده است."
      },
      {
        "id": "interval_days",
        "field": "interval_days",
        "question": "فاصله بین نوبت های مصرف کود چند روز است؟",
        "rationale": "عدد فاصله بین نوبت ها برای JSON نهایی لازم است."
      }
    ],
    "collected_data": {
      "crop_name": "گندم",
      "growth_stage": null,
      "objective": null,
      "applications": [
        {
          "fertilizer_name": "کود کامل",
          "formula": null,
          "amount": "35 کیلوگرم در هکتار",
          "application_method": "کودآبیاری",
          "timing": "هر چند وقت یک بار",
          "interval_days": null,
          "purpose": null
        }
      ],
      "notes": []
    },
    "final_plan": null
  }
}
```

---

## flow پیشنهادی فرانت‌اند برای کودهی

### درخواست اولیه

```json
{
  "message": "برای گندم از کود کامل استفاده می کنم."
}
```

### اگر incomplete بود

- از `questions` سوال‌ها را بگیر
- در UI نمایش بده
- پاسخ‌ها را جمع کن

### درخواست تکمیلی

```json
{
  "partial_plan": {
    "crop_name": "گندم",
    "growth_stage": null,
    "objective": null,
    "applications": [
      {
        "fertilizer_name": "کود کامل",
        "formula": null,
        "amount": null,
        "application_method": null,
        "timing": null,
        "interval_days": null,
        "purpose": null
      }
    ],
    "notes": []
  },
  "answers": {
    "growth_stage": "پنجه زنی",
    "formula": "20-20-20",
    "amount": "35 کیلوگرم در هکتار",
    "application_method": "کودآبیاری",
    "timing": "هر 12 روز یک بار",
    "interval_days": 12
  }
}
```

### اگر complete شد

- از `final_plan` استفاده کن

---

## نکات مهم برای فرانت‌اند

### 1. به `status` تکیه کنید

مهم‌ترین فیلد برای کنترل flow:

- `completed`
- `needs_clarification`

### 2. اگر `needs_clarification` بود

باید:

- `questions` را به کاربر نمایش دهید
- `partial_plan` را نگه دارید
- پاسخ‌های کاربر را در `answers` ارسال کنید

### 3. اگر `completed` بود

باید:

- `final_plan` را به عنوان نسخه نهایی برنامه ذخیره یا نمایش دهید

### 4. `collected_data` همیشه مهم است

حتی اگر برنامه ناقص باشد، `collected_data` نشان می‌دهد سیستم تا این لحظه چه چیزهایی را فهمیده است.

### 5. null در حالت ناقص طبیعی است

در حالت `needs_clarification` ممکن است بعضی فیلدهای `collected_data` `null` باشند.  
اما در حالت `completed` نباید فیلدهای اصلی ناقص باشند.

### 6. فرانت‌اند بهتر است سوال‌ها را به صورت step-by-step بپرسد

پیشنهاد:

- سوال اول را نشان بده
- جواب را بگیر
- همه جواب‌ها را در `answers` جمع کن
- دوباره API را صدا بزن

---

## جمع‌بندی تفاوت دو API

| API | موضوع | خروجی نهایی |
|---|---|---|
| `/api/irrigation/plan-from-text/` | استخراج برنامه آبیاری | `final_plan` با ساختار آبیاری |
| `/api/fertilization/plan-from-text/` | استخراج برنامه کودهی | `final_plan` با ساختار کودهی |

---

## مسیر فایل

این داکیومنت در این مسیر ذخیره شده:

`docs/irrigation_fertilization_plan_parser_apis.md`
