UPDATE
This commit is contained in:
@@ -15,3 +15,13 @@ DB_ROOT_PASSWORD=root
|
|||||||
# SMS.ir
|
# SMS.ir
|
||||||
SMS_IR_API_KEY=
|
SMS_IR_API_KEY=
|
||||||
SMS_IR_LINE_NUMBER=300000000000
|
SMS_IR_LINE_NUMBER=300000000000
|
||||||
|
|
||||||
|
# External API adapter
|
||||||
|
USE_EXTERNAL_API_MOCK=true
|
||||||
|
EXTERNAL_API_TIMEOUT=30
|
||||||
|
|
||||||
|
AI_SERVICE_BASE_URL=https://ai.example.com
|
||||||
|
AI_SERVICE_API_KEY=
|
||||||
|
|
||||||
|
SENSOR_HUB_SERVICE_BASE_URL=https://sensor-hub.example.com
|
||||||
|
SENSOR_HUB_SERVICE_API_KEY=
|
||||||
|
|||||||
+16
-2
@@ -1,6 +1,7 @@
|
|||||||
import secrets
|
import secrets
|
||||||
|
|
||||||
from django.contrib.auth import authenticate
|
from django.contrib.auth import authenticate, get_user_model
|
||||||
|
from django.db.models import Q
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.core.signing import BadSignature, SignatureExpired, TimestampSigner
|
from django.core.signing import BadSignature, SignatureExpired, TimestampSigner
|
||||||
@@ -130,8 +131,21 @@ class LoginView(APIView):
|
|||||||
identifier = serializer.validated_data["identifier"]
|
identifier = serializer.validated_data["identifier"]
|
||||||
password = serializer.validated_data["password"]
|
password = serializer.validated_data["password"]
|
||||||
|
|
||||||
user = authenticate(request, username=identifier, password=password)
|
User = get_user_model()
|
||||||
|
|
||||||
|
identifier = serializer.validated_data["identifier"]
|
||||||
|
password = serializer.validated_data["password"]
|
||||||
|
|
||||||
|
user_obj = User.objects.filter(
|
||||||
|
Q(username=identifier) | Q(email=identifier) | Q(phone_number=identifier)
|
||||||
|
).first()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if user_obj:
|
||||||
|
user = authenticate(request, username=user_obj.username, password=password)
|
||||||
|
else:
|
||||||
|
user = None
|
||||||
if user is None:
|
if user is None:
|
||||||
return Response(
|
return Response(
|
||||||
{"code": 401, "msg": "Invalid credentials."},
|
{"code": 401, "msg": "Invalid credentials."},
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ INSTALLED_APPS = [
|
|||||||
"irrigation_recommendation",
|
"irrigation_recommendation",
|
||||||
"fertilization_recommendation",
|
"fertilization_recommendation",
|
||||||
"farm_ai_assistant",
|
"farm_ai_assistant",
|
||||||
|
"external_api_adapter.apps.ExternalApiAdapterConfig",
|
||||||
"rest_framework",
|
"rest_framework",
|
||||||
"drf_spectacular",
|
"drf_spectacular",
|
||||||
"drf_spectacular_sidecar",
|
"drf_spectacular_sidecar",
|
||||||
@@ -134,3 +135,17 @@ SMS_IR_API_KEY = os.environ.get("SMS_IR_API_KEY", "")
|
|||||||
SMS_IR_LINE_NUMBER = int(os.environ.get("SMS_IR_LINE_NUMBER", "300000000000"))
|
SMS_IR_LINE_NUMBER = int(os.environ.get("SMS_IR_LINE_NUMBER", "300000000000"))
|
||||||
|
|
||||||
CORS_ALLOW_ALL_ORIGINS = DEBUG
|
CORS_ALLOW_ALL_ORIGINS = DEBUG
|
||||||
|
|
||||||
|
USE_EXTERNAL_API_MOCK = os.getenv("USE_EXTERNAL_API_MOCK", "false").lower() == "true"
|
||||||
|
EXTERNAL_API_TIMEOUT = int(os.getenv("EXTERNAL_API_TIMEOUT", "30"))
|
||||||
|
|
||||||
|
EXTERNAL_SERVICES = {
|
||||||
|
"ai": {
|
||||||
|
"base_url": os.getenv("AI_SERVICE_BASE_URL", ""),
|
||||||
|
"api_key": os.getenv("AI_SERVICE_API_KEY", ""),
|
||||||
|
},
|
||||||
|
"sensor_hub": {
|
||||||
|
"base_url": os.getenv("SENSOR_HUB_SERVICE_BASE_URL", ""),
|
||||||
|
"api_key": os.getenv("SENSOR_HUB_SERVICE_API_KEY", ""),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|||||||
+4
-2
@@ -11,7 +11,8 @@ from drf_spectacular.types import OpenApiTypes
|
|||||||
from drf_spectacular.utils import extend_schema, extend_schema_view
|
from drf_spectacular.utils import extend_schema, extend_schema_view
|
||||||
|
|
||||||
from config.swagger import code_response
|
from config.swagger import code_response
|
||||||
from .mock_data import ALL_CARDS, CONFIG
|
from external_api_adapter import request as external_api_request
|
||||||
|
from .mock_data import CONFIG
|
||||||
|
|
||||||
|
|
||||||
@extend_schema_view(
|
@extend_schema_view(
|
||||||
@@ -58,4 +59,5 @@ class FarmDashboardCardsView(APIView):
|
|||||||
permission_classes = []
|
permission_classes = []
|
||||||
|
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
return Response({"code": 200, "msg": "OK", "data": ALL_CARDS}, status=status.HTTP_200_OK)
|
adapter_response = external_api_request("ai", "/dashboard-data/status", method="GET")
|
||||||
|
return Response(adapter_response.data, status=adapter_response.status_code)
|
||||||
|
|||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
# Development: volumes mount source so code updates apply without rebuild
|
# Development: volumes mount source so code updates apply without rebuild
|
||||||
services:
|
services:
|
||||||
db:
|
db:
|
||||||
image: docker-mirror.liara.ir/mysql:8.0
|
image: mysql:8.0
|
||||||
environment:
|
environment:
|
||||||
MYSQL_DATABASE: ${DB_NAME:-croplogic}
|
MYSQL_DATABASE: ${DB_NAME:-croplogic}
|
||||||
MYSQL_USER: ${DB_USER:-croplogic}
|
MYSQL_USER: ${DB_USER:-croplogic}
|
||||||
@@ -16,7 +16,7 @@ services:
|
|||||||
retries: 5
|
retries: 5
|
||||||
|
|
||||||
phpmyadmin:
|
phpmyadmin:
|
||||||
image: docker-mirror.liara.ir/phpmyadmin:latest
|
image: phpmyadmin:latest
|
||||||
environment:
|
environment:
|
||||||
PMA_HOST: db
|
PMA_HOST: db
|
||||||
PMA_PORT: 3306
|
PMA_PORT: 3306
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
# External API Adapter
|
||||||
|
|
||||||
|
## Settings
|
||||||
|
|
||||||
|
```python
|
||||||
|
USE_EXTERNAL_API_MOCK = os.getenv("USE_EXTERNAL_API_MOCK", "false").lower() == "true"
|
||||||
|
|
||||||
|
EXTERNAL_SERVICES = {
|
||||||
|
"ai": {
|
||||||
|
"base_url": os.getenv("AI_SERVICE_BASE_URL", ""),
|
||||||
|
"api_key": os.getenv("AI_SERVICE_API_KEY", ""),
|
||||||
|
},
|
||||||
|
"sensor_hub": {
|
||||||
|
"base_url": os.getenv("SENSOR_HUB_SERVICE_BASE_URL", ""),
|
||||||
|
"api_key": os.getenv("SENSOR_HUB_SERVICE_API_KEY", ""),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```python
|
||||||
|
from rest_framework.response import Response
|
||||||
|
from rest_framework.views import APIView
|
||||||
|
|
||||||
|
from external_api_adapter import request
|
||||||
|
|
||||||
|
|
||||||
|
class PredictionProxyView(APIView):
|
||||||
|
def get(self, request_obj):
|
||||||
|
adapter_response = request("ai", "/predict")
|
||||||
|
return Response(adapter_response.data, status=adapter_response.status_code)
|
||||||
|
```
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
from .adapter import ExternalAPIAdapter, request
|
||||||
|
|
||||||
|
__all__ = ["ExternalAPIAdapter", "request"]
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
from dataclasses import dataclass, field
|
||||||
|
|
||||||
|
import requests
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
from .exceptions import ExternalAPIRequestError
|
||||||
|
from .mock_loader import MockLoader
|
||||||
|
from .services import ServiceRegistry
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class AdapterResponse:
|
||||||
|
status_code: int
|
||||||
|
data: object
|
||||||
|
headers: dict = field(default_factory=dict)
|
||||||
|
is_mock: bool = False
|
||||||
|
|
||||||
|
|
||||||
|
class ExternalAPIAdapter:
|
||||||
|
def __init__(self, service_registry=None, mock_loader=None):
|
||||||
|
self.service_registry = service_registry or ServiceRegistry()
|
||||||
|
self.mock_loader = mock_loader or MockLoader()
|
||||||
|
|
||||||
|
def request(self, service_name, path, method="GET", payload=None, query=None, headers=None):
|
||||||
|
request_method = method.upper()
|
||||||
|
self._validate_method(request_method)
|
||||||
|
service = self.service_registry.get(service_name)
|
||||||
|
|
||||||
|
if getattr(settings, "USE_EXTERNAL_API_MOCK", False):
|
||||||
|
mock_response = self.mock_loader.load(service_name=service_name, path=path, method=request_method)
|
||||||
|
return AdapterResponse(
|
||||||
|
status_code=mock_response.status_code,
|
||||||
|
data=mock_response.data,
|
||||||
|
headers={"X-Mock-File": mock_response.file_path},
|
||||||
|
is_mock=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
return self._call_real_api(
|
||||||
|
service=service,
|
||||||
|
path=path,
|
||||||
|
method=request_method,
|
||||||
|
payload=payload,
|
||||||
|
query=query,
|
||||||
|
headers=headers,
|
||||||
|
)
|
||||||
|
|
||||||
|
def _call_real_api(self, service, path, method, payload=None, query=None, headers=None):
|
||||||
|
base_url = service.get("base_url", "").rstrip("/")
|
||||||
|
api_key = service.get("api_key", "")
|
||||||
|
if not base_url:
|
||||||
|
raise ExternalAPIRequestError("External service base_url is not configured.")
|
||||||
|
url = f"{base_url}/{str(path).lstrip('/')}"
|
||||||
|
|
||||||
|
request_headers = {
|
||||||
|
"Authorization": f"Bearer {api_key}",
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
}
|
||||||
|
if headers:
|
||||||
|
request_headers.update(headers)
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = requests.request(
|
||||||
|
method=method,
|
||||||
|
url=url,
|
||||||
|
json=payload,
|
||||||
|
params=query,
|
||||||
|
headers=request_headers,
|
||||||
|
timeout=getattr(settings, "EXTERNAL_API_TIMEOUT", 30),
|
||||||
|
)
|
||||||
|
except requests.RequestException as exc:
|
||||||
|
raise ExternalAPIRequestError(f"External API request failed for '{url}': {exc}") from exc
|
||||||
|
|
||||||
|
try:
|
||||||
|
response_data = response.json()
|
||||||
|
except ValueError:
|
||||||
|
response_data = response.text
|
||||||
|
|
||||||
|
return AdapterResponse(
|
||||||
|
status_code=response.status_code,
|
||||||
|
data=response_data,
|
||||||
|
headers=dict(response.headers),
|
||||||
|
is_mock=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _validate_method(method):
|
||||||
|
supported_methods = {"GET", "POST", "PUT", "DELETE"}
|
||||||
|
if method not in supported_methods:
|
||||||
|
raise ValueError(f"Unsupported HTTP method '{method}'. Supported methods: {sorted(supported_methods)}")
|
||||||
|
|
||||||
|
|
||||||
|
_default_adapter = ExternalAPIAdapter()
|
||||||
|
|
||||||
|
|
||||||
|
def request(service_name, path, method="GET", payload=None, query=None, headers=None):
|
||||||
|
return _default_adapter.request(
|
||||||
|
service_name=service_name,
|
||||||
|
path=path,
|
||||||
|
method=method,
|
||||||
|
payload=payload,
|
||||||
|
query=query,
|
||||||
|
headers=headers,
|
||||||
|
)
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class ExternalApiAdapterConfig(AppConfig):
|
||||||
|
default_auto_field = "django.db.models.BigAutoField"
|
||||||
|
name = "external_api_adapter"
|
||||||
|
verbose_name = "External API Adapter"
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
class ExternalAPIAdapterError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ServiceNotFound(ExternalAPIAdapterError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class MockDirectoryNotFound(ExternalAPIAdapterError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class MockFileNotFound(ExternalAPIAdapterError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ExternalAPIRequestError(ExternalAPIAdapterError):
|
||||||
|
pass
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"code": 202,
|
||||||
|
"msg": "dashboard task queued",
|
||||||
|
"data": {
|
||||||
|
"task_id": "dashboard-task-123",
|
||||||
|
"status_url": "/api/dashboard-data/dashboard-task-123/status/"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"code": 400,
|
||||||
|
"msg": "پارامتر sensor_id الزامی است.",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"task_id": "dashboard-task-123",
|
||||||
|
"status": "FAILURE",
|
||||||
|
"error": "خطا در ساخت کارتهای داشبورد."
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"task_id": "dashboard-task-123",
|
||||||
|
"status": "PENDING",
|
||||||
|
"message": "تسک در صف یا یافت نشد."
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"task_id": "dashboard-task-123",
|
||||||
|
"status": "PROGRESS",
|
||||||
|
"progress": {
|
||||||
|
"current": 5,
|
||||||
|
"total": 15,
|
||||||
|
"card": "sensorValuesList",
|
||||||
|
"message": "processing sensorValuesList"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"task_id": "dashboard-task-123",
|
||||||
|
"status": "SUCCESS",
|
||||||
|
"result": {
|
||||||
|
"sensor_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||||
|
"all_cards": {
|
||||||
|
"farmOverviewKpis": {
|
||||||
|
"healthScore": 82,
|
||||||
|
"activeAlerts": 2,
|
||||||
|
"waterNeedMm": 18.4
|
||||||
|
},
|
||||||
|
"sensorValuesList": {
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"label": "رطوبت خاک",
|
||||||
|
"value": 45.2,
|
||||||
|
"unit": "%"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "دما خاک",
|
||||||
|
"value": 22.5,
|
||||||
|
"unit": "°C"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"recommendationsList": {
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"recommendation_title": "تنظیم نوبت آبیاری",
|
||||||
|
"suggested_action": "آبیاری بعدی را صبح فردا انجام دهید.",
|
||||||
|
"urgency_level": "high"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"code": 202,
|
||||||
|
"msg": "تسک توصیه کودهی در صف قرار گرفت.",
|
||||||
|
"data": {
|
||||||
|
"task_id": "fert-task-123",
|
||||||
|
"status_url": "/api/fertilization/recommend/fert-task-123/status/"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"code": 400,
|
||||||
|
"msg": "داده نامعتبر.",
|
||||||
|
"data": {
|
||||||
|
"sensor_uuid": [
|
||||||
|
"This field is required."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"task_id": "fert-task-123",
|
||||||
|
"status": "FAILURE",
|
||||||
|
"error": "خطا در دریافت توصیه کودهی."
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"task_id": "fert-task-123",
|
||||||
|
"status": "PENDING",
|
||||||
|
"message": "تسک در صف یا یافت نشد."
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"task_id": "fert-task-123",
|
||||||
|
"status": "PROGRESS",
|
||||||
|
"progress": {
|
||||||
|
"message": "در حال پردازش توصیه کودهی..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"task_id": "fert-task-123",
|
||||||
|
"status": "SUCCESS",
|
||||||
|
"result": {
|
||||||
|
"plan": {
|
||||||
|
"npkRatio": "20-20-20",
|
||||||
|
"amountPerHectare": "150 kg/ha",
|
||||||
|
"applicationMethod": "کودآبیاری در دو نوبت",
|
||||||
|
"applicationInterval": "هر ۱۰ روز",
|
||||||
|
"reasoning": "نیتروژن و پتاسیم خاک در محدوده متوسط است و گیاه در فاز رویشی نیاز تغذیهای بالاتری دارد."
|
||||||
|
},
|
||||||
|
"raw_response": "{\"plan\":{\"npkRatio\":\"20-20-20\"}}",
|
||||||
|
"status": "completed"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,604 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"method": "POST",
|
||||||
|
"path": "/api/dashboard-data/generate/",
|
||||||
|
"status_code": 202,
|
||||||
|
"description": "Dashboard data task queued",
|
||||||
|
"file": "json/mock_data/dashboard-data/generate/post_202.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "POST",
|
||||||
|
"path": "/api/dashboard-data/generate/",
|
||||||
|
"status_code": 400,
|
||||||
|
"description": "Missing sensor_id",
|
||||||
|
"file": "json/mock_data/dashboard-data/generate/post_400.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/dashboard-data/{task_id}/status/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Pending dashboard task",
|
||||||
|
"file": "json/mock_data/dashboard-data/status/get_200_pending.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/dashboard-data/{task_id}/status/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Dashboard task in progress",
|
||||||
|
"file": "json/mock_data/dashboard-data/status/get_200_progress.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/dashboard-data/{task_id}/status/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Successful dashboard task",
|
||||||
|
"file": "json/mock_data/dashboard-data/status/get_200_success.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/dashboard-data/{task_id}/status/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Failed dashboard task",
|
||||||
|
"file": "json/mock_data/dashboard-data/status/get_200_failure.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "POST",
|
||||||
|
"path": "/api/fertilization/recommend/",
|
||||||
|
"status_code": 202,
|
||||||
|
"description": "Fertilization task queued",
|
||||||
|
"file": "json/mock_data/fertilization/recommend/post_202.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "POST",
|
||||||
|
"path": "/api/fertilization/recommend/",
|
||||||
|
"status_code": 400,
|
||||||
|
"description": "Validation error",
|
||||||
|
"file": "json/mock_data/fertilization/recommend/post_400.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/fertilization/recommend/{task_id}/status/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Fertilization status pending",
|
||||||
|
"file": "json/mock_data/fertilization/status/get_200_pending.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/fertilization/recommend/{task_id}/status/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Fertilization status progress",
|
||||||
|
"file": "json/mock_data/fertilization/status/get_200_progress.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/fertilization/recommend/{task_id}/status/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Fertilization status success",
|
||||||
|
"file": "json/mock_data/fertilization/status/get_200_success.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/fertilization/recommend/{task_id}/status/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Fertilization status failure",
|
||||||
|
"file": "json/mock_data/fertilization/status/get_200_failure.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/irrigation/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "List irrigation methods",
|
||||||
|
"file": "json/mock_data/irrigation/methods/get_200.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "POST",
|
||||||
|
"path": "/api/irrigation/",
|
||||||
|
"status_code": 201,
|
||||||
|
"description": "Create irrigation method",
|
||||||
|
"file": "json/mock_data/irrigation/methods/post_201.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "POST",
|
||||||
|
"path": "/api/irrigation/",
|
||||||
|
"status_code": 400,
|
||||||
|
"description": "Irrigation create validation error",
|
||||||
|
"file": "json/mock_data/irrigation/methods/post_400.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "POST",
|
||||||
|
"path": "/api/irrigation/recommend/",
|
||||||
|
"status_code": 202,
|
||||||
|
"description": "Irrigation recommendation task queued",
|
||||||
|
"file": "json/mock_data/irrigation/recommend/post_202.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "POST",
|
||||||
|
"path": "/api/irrigation/recommend/",
|
||||||
|
"status_code": 400,
|
||||||
|
"description": "Irrigation recommendation validation error",
|
||||||
|
"file": "json/mock_data/irrigation/recommend/post_400.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/irrigation/recommend/{task_id}/status/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Irrigation recommendation status pending",
|
||||||
|
"file": "json/mock_data/irrigation/recommend/status/get_200_pending.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/irrigation/recommend/{task_id}/status/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Irrigation recommendation status progress",
|
||||||
|
"file": "json/mock_data/irrigation/recommend/status/get_200_progress.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/irrigation/recommend/{task_id}/status/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Irrigation recommendation status success",
|
||||||
|
"file": "json/mock_data/irrigation/recommend/status/get_200_success.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/irrigation/recommend/{task_id}/status/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Irrigation recommendation status failure",
|
||||||
|
"file": "json/mock_data/irrigation/recommend/status/get_200_failure.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/irrigation/{pk}/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Irrigation method get success",
|
||||||
|
"file": "json/mock_data/irrigation/method-detail/get_200.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/irrigation/{pk}/",
|
||||||
|
"status_code": 404,
|
||||||
|
"description": "Irrigation method get not found",
|
||||||
|
"file": "json/mock_data/irrigation/method-detail/get_404.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "PUT",
|
||||||
|
"path": "/api/irrigation/{pk}/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Irrigation method put success",
|
||||||
|
"file": "json/mock_data/irrigation/method-detail/put_200.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "PUT",
|
||||||
|
"path": "/api/irrigation/{pk}/",
|
||||||
|
"status_code": 400,
|
||||||
|
"description": "Irrigation method put validation error",
|
||||||
|
"file": "json/mock_data/irrigation/method-detail/put_400.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "PUT",
|
||||||
|
"path": "/api/irrigation/{pk}/",
|
||||||
|
"status_code": 404,
|
||||||
|
"description": "Irrigation method put not found",
|
||||||
|
"file": "json/mock_data/irrigation/method-detail/put_404.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "PATCH",
|
||||||
|
"path": "/api/irrigation/{pk}/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Irrigation method patch success",
|
||||||
|
"file": "json/mock_data/irrigation/method-detail/patch_200.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "PATCH",
|
||||||
|
"path": "/api/irrigation/{pk}/",
|
||||||
|
"status_code": 400,
|
||||||
|
"description": "Irrigation method patch validation error",
|
||||||
|
"file": "json/mock_data/irrigation/method-detail/patch_400.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "PATCH",
|
||||||
|
"path": "/api/irrigation/{pk}/",
|
||||||
|
"status_code": 404,
|
||||||
|
"description": "Irrigation method patch not found",
|
||||||
|
"file": "json/mock_data/irrigation/method-detail/patch_404.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "DELETE",
|
||||||
|
"path": "/api/irrigation/{pk}/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Delete irrigation method",
|
||||||
|
"file": "json/mock_data/irrigation/method-detail/delete_200.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "DELETE",
|
||||||
|
"path": "/api/irrigation/{pk}/",
|
||||||
|
"status_code": 404,
|
||||||
|
"description": "Delete irrigation method not found",
|
||||||
|
"file": "json/mock_data/irrigation/method-detail/delete_404.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/soil-data/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Soil data served from database",
|
||||||
|
"file": "json/mock_data/soil-data/get_200_database.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/soil-data/",
|
||||||
|
"status_code": 202,
|
||||||
|
"description": "Soil data fetch task queued",
|
||||||
|
"file": "json/mock_data/soil-data/get_202_queued.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/soil-data/",
|
||||||
|
"status_code": 400,
|
||||||
|
"description": "Soil data validation error",
|
||||||
|
"file": "json/mock_data/soil-data/get_400.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "POST",
|
||||||
|
"path": "/api/soil-data/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Soil data POST served from database",
|
||||||
|
"file": "json/mock_data/soil-data/post_200_database.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "POST",
|
||||||
|
"path": "/api/soil-data/",
|
||||||
|
"status_code": 202,
|
||||||
|
"description": "Soil data POST task queued",
|
||||||
|
"file": "json/mock_data/soil-data/post_202_queued.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "POST",
|
||||||
|
"path": "/api/soil-data/",
|
||||||
|
"status_code": 400,
|
||||||
|
"description": "Soil data POST validation error",
|
||||||
|
"file": "json/mock_data/soil-data/post_400.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/soil-data/tasks/{task_id}/status/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Soil task status pending",
|
||||||
|
"file": "json/mock_data/soil-data/status/get_200_pending.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/soil-data/tasks/{task_id}/status/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Soil task status progress",
|
||||||
|
"file": "json/mock_data/soil-data/status/get_200_progress.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/soil-data/tasks/{task_id}/status/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Soil task status success",
|
||||||
|
"file": "json/mock_data/soil-data/status/get_200_success.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/soil-data/tasks/{task_id}/status/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Soil task status failure",
|
||||||
|
"file": "json/mock_data/soil-data/status/get_200_failure.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/plants/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "List plants",
|
||||||
|
"file": "json/mock_data/plant/list-get_200.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "POST",
|
||||||
|
"path": "/api/plants/",
|
||||||
|
"status_code": 201,
|
||||||
|
"description": "Create plant",
|
||||||
|
"file": "json/mock_data/plant/create-post_201.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "POST",
|
||||||
|
"path": "/api/plants/",
|
||||||
|
"status_code": 400,
|
||||||
|
"description": "Plant create validation error",
|
||||||
|
"file": "json/mock_data/plant/create-post_400.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/plants/{pk}/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Plant detail get success",
|
||||||
|
"file": "json/mock_data/plant/detail-get_200.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/plants/{pk}/",
|
||||||
|
"status_code": 404,
|
||||||
|
"description": "Plant detail get not found",
|
||||||
|
"file": "json/mock_data/plant/detail-get_404.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "PUT",
|
||||||
|
"path": "/api/plants/{pk}/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Plant detail put success",
|
||||||
|
"file": "json/mock_data/plant/detail-put_200.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "PUT",
|
||||||
|
"path": "/api/plants/{pk}/",
|
||||||
|
"status_code": 400,
|
||||||
|
"description": "Plant detail put validation error",
|
||||||
|
"file": "json/mock_data/plant/detail-put_400.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "PUT",
|
||||||
|
"path": "/api/plants/{pk}/",
|
||||||
|
"status_code": 404,
|
||||||
|
"description": "Plant detail put not found",
|
||||||
|
"file": "json/mock_data/plant/detail-put_404.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "PATCH",
|
||||||
|
"path": "/api/plants/{pk}/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Plant detail patch success",
|
||||||
|
"file": "json/mock_data/plant/detail-patch_200.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "PATCH",
|
||||||
|
"path": "/api/plants/{pk}/",
|
||||||
|
"status_code": 400,
|
||||||
|
"description": "Plant detail patch validation error",
|
||||||
|
"file": "json/mock_data/plant/detail-patch_400.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "PATCH",
|
||||||
|
"path": "/api/plants/{pk}/",
|
||||||
|
"status_code": 404,
|
||||||
|
"description": "Plant detail patch not found",
|
||||||
|
"file": "json/mock_data/plant/detail-patch_404.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "DELETE",
|
||||||
|
"path": "/api/plants/{pk}/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Delete plant success",
|
||||||
|
"file": "json/mock_data/plant/detail-delete_200.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "DELETE",
|
||||||
|
"path": "/api/plants/{pk}/",
|
||||||
|
"status_code": 404,
|
||||||
|
"description": "Delete plant not found",
|
||||||
|
"file": "json/mock_data/plant/detail-delete_404.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "POST",
|
||||||
|
"path": "/api/plants/fetch-info/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Fetch plant info success",
|
||||||
|
"file": "json/mock_data/plant/fetch-info-post_200.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "POST",
|
||||||
|
"path": "/api/plants/fetch-info/",
|
||||||
|
"status_code": 400,
|
||||||
|
"description": "Fetch plant info missing name",
|
||||||
|
"file": "json/mock_data/plant/fetch-info-post_400.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "POST",
|
||||||
|
"path": "/api/plants/fetch-info/",
|
||||||
|
"status_code": 503,
|
||||||
|
"description": "Fetch plant info service unavailable",
|
||||||
|
"file": "json/mock_data/plant/fetch-info-post_503.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "POST",
|
||||||
|
"path": "/api/rag/chat/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "RAG chat streaming response",
|
||||||
|
"file": "json/mock_data/rag/chat-post_200_stream.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "POST",
|
||||||
|
"path": "/api/rag/chat/",
|
||||||
|
"status_code": 400,
|
||||||
|
"description": "Missing query",
|
||||||
|
"file": "json/mock_data/rag/chat-post_400_missing_query.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "POST",
|
||||||
|
"path": "/api/rag/chat/",
|
||||||
|
"status_code": 400,
|
||||||
|
"description": "Invalid service id",
|
||||||
|
"file": "json/mock_data/rag/chat-post_400_invalid_service.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "POST",
|
||||||
|
"path": "/api/rag/chat/",
|
||||||
|
"status_code": 400,
|
||||||
|
"description": "Missing user_id for service",
|
||||||
|
"file": "json/mock_data/rag/chat-post_400_missing_user.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "POST",
|
||||||
|
"path": "/api/rag/recommend/irrigation/",
|
||||||
|
"status_code": 202,
|
||||||
|
"description": "RAG irrigation task queued",
|
||||||
|
"file": "json/mock_data/rag/irrigation/post_202.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "POST",
|
||||||
|
"path": "/api/rag/recommend/irrigation/",
|
||||||
|
"status_code": 400,
|
||||||
|
"description": "RAG irrigation validation error",
|
||||||
|
"file": "json/mock_data/rag/irrigation/post_400.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/rag/recommend/irrigation/{task_id}/status/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "RAG irrigation status pending",
|
||||||
|
"file": "json/mock_data/rag/irrigation/status/get_200_pending.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/rag/recommend/irrigation/{task_id}/status/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "RAG irrigation status progress",
|
||||||
|
"file": "json/mock_data/rag/irrigation/status/get_200_progress.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/rag/recommend/irrigation/{task_id}/status/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "RAG irrigation status success",
|
||||||
|
"file": "json/mock_data/rag/irrigation/status/get_200_success.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/rag/recommend/irrigation/{task_id}/status/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "RAG irrigation status failure",
|
||||||
|
"file": "json/mock_data/rag/irrigation/status/get_200_failure.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "POST",
|
||||||
|
"path": "/api/rag/recommend/fertilization/",
|
||||||
|
"status_code": 202,
|
||||||
|
"description": "RAG fertilization task queued",
|
||||||
|
"file": "json/mock_data/rag/fertilization/post_202.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "POST",
|
||||||
|
"path": "/api/rag/recommend/fertilization/",
|
||||||
|
"status_code": 400,
|
||||||
|
"description": "RAG fertilization validation error",
|
||||||
|
"file": "json/mock_data/rag/fertilization/post_400.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/rag/recommend/fertilization/{task_id}/status/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "RAG fertilization status pending",
|
||||||
|
"file": "json/mock_data/rag/fertilization/status/get_200_pending.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/rag/recommend/fertilization/{task_id}/status/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "RAG fertilization status progress",
|
||||||
|
"file": "json/mock_data/rag/fertilization/status/get_200_progress.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/rag/recommend/fertilization/{task_id}/status/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "RAG fertilization status success",
|
||||||
|
"file": "json/mock_data/rag/fertilization/status/get_200_success.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/rag/recommend/fertilization/{task_id}/status/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "RAG fertilization status failure",
|
||||||
|
"file": "json/mock_data/rag/fertilization/status/get_200_failure.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "PUT",
|
||||||
|
"path": "/api/sensor-data/{uuid_sensor}/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Sensor update put success",
|
||||||
|
"file": "json/mock_data/sensor-data/update-put_200.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "PUT",
|
||||||
|
"path": "/api/sensor-data/{uuid_sensor}/",
|
||||||
|
"status_code": 400,
|
||||||
|
"description": "Sensor update put validation error",
|
||||||
|
"file": "json/mock_data/sensor-data/update-put_400.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "PUT",
|
||||||
|
"path": "/api/sensor-data/{uuid_sensor}/",
|
||||||
|
"status_code": 404,
|
||||||
|
"description": "Sensor update put location not found",
|
||||||
|
"file": "json/mock_data/sensor-data/update-put_404.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "PATCH",
|
||||||
|
"path": "/api/sensor-data/{uuid_sensor}/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Sensor update patch success",
|
||||||
|
"file": "json/mock_data/sensor-data/update-patch_200.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "PATCH",
|
||||||
|
"path": "/api/sensor-data/{uuid_sensor}/",
|
||||||
|
"status_code": 400,
|
||||||
|
"description": "Sensor update patch validation error",
|
||||||
|
"file": "json/mock_data/sensor-data/update-patch_400.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "PATCH",
|
||||||
|
"path": "/api/sensor-data/{uuid_sensor}/",
|
||||||
|
"status_code": 404,
|
||||||
|
"description": "Sensor update patch location not found",
|
||||||
|
"file": "json/mock_data/sensor-data/update-patch_404.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "POST",
|
||||||
|
"path": "/api/sensor-data/parameters/",
|
||||||
|
"status_code": 201,
|
||||||
|
"description": "Create sensor parameter",
|
||||||
|
"file": "json/mock_data/sensor-data/parameters-post_201.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "POST",
|
||||||
|
"path": "/api/sensor-data/parameters/",
|
||||||
|
"status_code": 400,
|
||||||
|
"description": "Sensor parameter validation error",
|
||||||
|
"file": "json/mock_data/sensor-data/parameters-post_400.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "POST",
|
||||||
|
"path": "/api/tasks/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Task trigger success",
|
||||||
|
"file": "json/mock_data/tasks/post_200.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/tasks/{task_id}/status/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Task status pending",
|
||||||
|
"file": "json/mock_data/tasks/status/get_200_pending.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/tasks/{task_id}/status/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Task status progress",
|
||||||
|
"file": "json/mock_data/tasks/status/get_200_progress.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/tasks/{task_id}/status/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Task status success",
|
||||||
|
"file": "json/mock_data/tasks/status/get_200_success.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "GET",
|
||||||
|
"path": "/api/tasks/{task_id}/status/",
|
||||||
|
"status_code": 200,
|
||||||
|
"description": "Task status failure",
|
||||||
|
"file": "json/mock_data/tasks/status/get_200_failure.json"
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "روش آبیاری با موفقیت حذف شد.",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"code": 404,
|
||||||
|
"msg": "روش آبیاری یافت نشد.",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"id": 1,
|
||||||
|
"name": "آبیاری قطرهای",
|
||||||
|
"category": "موضعی",
|
||||||
|
"description": "آبیاری با دبی کم و راندمان بالا",
|
||||||
|
"water_efficiency_percent": 90.0,
|
||||||
|
"water_pressure_required": "۱-۲ اتمسفر",
|
||||||
|
"flow_rate": "۲-۸ لیتر در ساعت",
|
||||||
|
"coverage_area": "بسته به طراحی سیستم",
|
||||||
|
"soil_type": "اکثر خاکها",
|
||||||
|
"climate_suitability": "گرم و خشک",
|
||||||
|
"created_at": "2025-03-20T10:00:00Z",
|
||||||
|
"updated_at": "2025-03-24T10:00:00Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"code": 404,
|
||||||
|
"msg": "روش آبیاری یافت نشد.",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"id": 1,
|
||||||
|
"name": "آبیاری قطرهای",
|
||||||
|
"category": "موضعی",
|
||||||
|
"description": "آبیاری با دبی کم و راندمان بالا",
|
||||||
|
"water_efficiency_percent": 90.0,
|
||||||
|
"water_pressure_required": "۱-۲ اتمسفر",
|
||||||
|
"flow_rate": "۲-۸ لیتر در ساعت",
|
||||||
|
"coverage_area": "بسته به طراحی سیستم",
|
||||||
|
"soil_type": "اکثر خاکها",
|
||||||
|
"climate_suitability": "گرم و خشک",
|
||||||
|
"created_at": "2025-03-20T10:00:00Z",
|
||||||
|
"updated_at": "2025-03-24T10:00:00Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"code": 400,
|
||||||
|
"msg": "داده نامعتبر.",
|
||||||
|
"data": {
|
||||||
|
"name": [
|
||||||
|
"This field may not be blank."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"code": 404,
|
||||||
|
"msg": "روش آبیاری یافت نشد.",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"id": 1,
|
||||||
|
"name": "آبیاری قطرهای",
|
||||||
|
"category": "موضعی",
|
||||||
|
"description": "آبیاری با دبی کم و راندمان بالا",
|
||||||
|
"water_efficiency_percent": 90.0,
|
||||||
|
"water_pressure_required": "۱-۲ اتمسفر",
|
||||||
|
"flow_rate": "۲-۸ لیتر در ساعت",
|
||||||
|
"coverage_area": "بسته به طراحی سیستم",
|
||||||
|
"soil_type": "اکثر خاکها",
|
||||||
|
"climate_suitability": "گرم و خشک",
|
||||||
|
"created_at": "2025-03-20T10:00:00Z",
|
||||||
|
"updated_at": "2025-03-24T10:00:00Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"code": 400,
|
||||||
|
"msg": "داده نامعتبر.",
|
||||||
|
"data": {
|
||||||
|
"name": [
|
||||||
|
"This field may not be blank."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"code": 404,
|
||||||
|
"msg": "روش آبیاری یافت نشد.",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "آبیاری قطرهای",
|
||||||
|
"category": "موضعی",
|
||||||
|
"description": "آبیاری با دبی کم و راندمان بالا",
|
||||||
|
"water_efficiency_percent": 90.0,
|
||||||
|
"water_pressure_required": "۱-۲ اتمسفر",
|
||||||
|
"flow_rate": "۲-۸ لیتر در ساعت",
|
||||||
|
"coverage_area": "بسته به طراحی سیستم",
|
||||||
|
"soil_type": "اکثر خاکها",
|
||||||
|
"climate_suitability": "گرم و خشک",
|
||||||
|
"created_at": "2025-03-20T10:00:00Z",
|
||||||
|
"updated_at": "2025-03-24T10:00:00Z"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"code": 201,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"id": 1,
|
||||||
|
"name": "آبیاری قطرهای",
|
||||||
|
"category": "موضعی",
|
||||||
|
"description": "آبیاری با دبی کم و راندمان بالا",
|
||||||
|
"water_efficiency_percent": 90.0,
|
||||||
|
"water_pressure_required": "۱-۲ اتمسفر",
|
||||||
|
"flow_rate": "۲-۸ لیتر در ساعت",
|
||||||
|
"coverage_area": "بسته به طراحی سیستم",
|
||||||
|
"soil_type": "اکثر خاکها",
|
||||||
|
"climate_suitability": "گرم و خشک",
|
||||||
|
"created_at": "2025-03-20T10:00:00Z",
|
||||||
|
"updated_at": "2025-03-24T10:00:00Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"code": 400,
|
||||||
|
"msg": "داده نامعتبر.",
|
||||||
|
"data": {
|
||||||
|
"name": [
|
||||||
|
"This field is required."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"code": 202,
|
||||||
|
"msg": "تسک توصیه آبیاری در صف قرار گرفت.",
|
||||||
|
"data": {
|
||||||
|
"task_id": "irr-task-123",
|
||||||
|
"status_url": "/api/irrigation/recommend/irr-task-123/status/"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"code": 400,
|
||||||
|
"msg": "داده نامعتبر.",
|
||||||
|
"data": {
|
||||||
|
"sensor_uuid": [
|
||||||
|
"This field is required."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"task_id": "irr-task-123",
|
||||||
|
"status": "FAILURE",
|
||||||
|
"error": "خطا در دریافت توصیه آبیاری."
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"task_id": "irr-task-123",
|
||||||
|
"status": "PENDING",
|
||||||
|
"message": "تسک در صف یا یافت نشد."
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"task_id": "irr-task-123",
|
||||||
|
"status": "PROGRESS",
|
||||||
|
"progress": {
|
||||||
|
"message": "در حال پردازش توصیه آبیاری..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"task_id": "irr-task-123",
|
||||||
|
"status": "SUCCESS",
|
||||||
|
"result": {
|
||||||
|
"plan": {
|
||||||
|
"frequencyPerWeek": 3,
|
||||||
|
"durationMinutes": 42,
|
||||||
|
"bestTimeOfDay": "صبح زود",
|
||||||
|
"moistureLevel": 68,
|
||||||
|
"warning": "در صورت بارش موثر، نوبت سوم این هفته را حذف کنید."
|
||||||
|
},
|
||||||
|
"raw_response": "{\"plan\":{\"frequencyPerWeek\":3,\"durationMinutes\":42}}",
|
||||||
|
"water_balance": {
|
||||||
|
"daily": [
|
||||||
|
{
|
||||||
|
"forecast_date": "2025-03-25",
|
||||||
|
"et0_mm": 4.7,
|
||||||
|
"etc_mm": 5.6,
|
||||||
|
"effective_rainfall_mm": 0.0,
|
||||||
|
"gross_irrigation_mm": 6.2,
|
||||||
|
"irrigation_timing": "06:00-08:00"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"crop_profile": {
|
||||||
|
"kc_initial": 0.6,
|
||||||
|
"kc_mid": 1.15,
|
||||||
|
"kc_end": 0.8
|
||||||
|
},
|
||||||
|
"active_kc": 1.15
|
||||||
|
},
|
||||||
|
"status": "completed"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"code": 201,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"id": 1,
|
||||||
|
"name": "گوجهفرنگی",
|
||||||
|
"light": "آفتاب کامل",
|
||||||
|
"watering": "منظم، هفتهای ۲ تا ۳ بار",
|
||||||
|
"soil": "لومی، غنی از مواد آلی",
|
||||||
|
"temperature": "۲۰ تا ۳۰ درجه سانتیگراد",
|
||||||
|
"planting_season": "بهار",
|
||||||
|
"harvest_time": "۷۰ تا ۹۰ روز پس از کاشت",
|
||||||
|
"spacing": "۴۵ تا ۶۰ سانتیمتر",
|
||||||
|
"fertilizer": "کود NPK متعادل",
|
||||||
|
"created_at": "2025-03-20T10:00:00Z",
|
||||||
|
"updated_at": "2025-03-24T10:00:00Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"code": 400,
|
||||||
|
"msg": "داده نامعتبر.",
|
||||||
|
"data": {
|
||||||
|
"name": [
|
||||||
|
"This field is required."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "گیاه با موفقیت حذف شد.",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"code": 404,
|
||||||
|
"msg": "گیاه یافت نشد.",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"id": 1,
|
||||||
|
"name": "گوجهفرنگی",
|
||||||
|
"light": "آفتاب کامل",
|
||||||
|
"watering": "منظم، هفتهای ۲ تا ۳ بار",
|
||||||
|
"soil": "لومی، غنی از مواد آلی",
|
||||||
|
"temperature": "۲۰ تا ۳۰ درجه سانتیگراد",
|
||||||
|
"planting_season": "بهار",
|
||||||
|
"harvest_time": "۷۰ تا ۹۰ روز پس از کاشت",
|
||||||
|
"spacing": "۴۵ تا ۶۰ سانتیمتر",
|
||||||
|
"fertilizer": "کود NPK متعادل",
|
||||||
|
"created_at": "2025-03-20T10:00:00Z",
|
||||||
|
"updated_at": "2025-03-24T10:00:00Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"code": 404,
|
||||||
|
"msg": "گیاه یافت نشد.",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"id": 1,
|
||||||
|
"name": "گوجهفرنگی",
|
||||||
|
"light": "آفتاب کامل",
|
||||||
|
"watering": "منظم، هفتهای ۲ تا ۳ بار",
|
||||||
|
"soil": "لومی، غنی از مواد آلی",
|
||||||
|
"temperature": "۲۰ تا ۳۰ درجه سانتیگراد",
|
||||||
|
"planting_season": "بهار",
|
||||||
|
"harvest_time": "۷۰ تا ۹۰ روز پس از کاشت",
|
||||||
|
"spacing": "۴۵ تا ۶۰ سانتیمتر",
|
||||||
|
"fertilizer": "کود NPK متعادل",
|
||||||
|
"created_at": "2025-03-20T10:00:00Z",
|
||||||
|
"updated_at": "2025-03-24T10:00:00Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"code": 400,
|
||||||
|
"msg": "داده نامعتبر.",
|
||||||
|
"data": {
|
||||||
|
"name": [
|
||||||
|
"This field may not be blank."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"code": 404,
|
||||||
|
"msg": "گیاه یافت نشد.",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"id": 1,
|
||||||
|
"name": "گوجهفرنگی",
|
||||||
|
"light": "آفتاب کامل",
|
||||||
|
"watering": "منظم، هفتهای ۲ تا ۳ بار",
|
||||||
|
"soil": "لومی، غنی از مواد آلی",
|
||||||
|
"temperature": "۲۰ تا ۳۰ درجه سانتیگراد",
|
||||||
|
"planting_season": "بهار",
|
||||||
|
"harvest_time": "۷۰ تا ۹۰ روز پس از کاشت",
|
||||||
|
"spacing": "۴۵ تا ۶۰ سانتیمتر",
|
||||||
|
"fertilizer": "کود NPK متعادل",
|
||||||
|
"created_at": "2025-03-20T10:00:00Z",
|
||||||
|
"updated_at": "2025-03-24T10:00:00Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"code": 400,
|
||||||
|
"msg": "داده نامعتبر.",
|
||||||
|
"data": {
|
||||||
|
"name": [
|
||||||
|
"This field may not be blank."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"code": 404,
|
||||||
|
"msg": "گیاه یافت نشد.",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"id": 1,
|
||||||
|
"name": "گوجهفرنگی",
|
||||||
|
"light": "آفتاب کامل",
|
||||||
|
"watering": "منظم، هفتهای ۲ تا ۳ بار",
|
||||||
|
"soil": "لومی، غنی از مواد آلی",
|
||||||
|
"temperature": "۲۰ تا ۳۰ درجه سانتیگراد",
|
||||||
|
"planting_season": "بهار",
|
||||||
|
"harvest_time": "۷۰ تا ۹۰ روز پس از کاشت",
|
||||||
|
"spacing": "۴۵ تا ۶۰ سانتیمتر",
|
||||||
|
"fertilizer": "کود NPK متعادل",
|
||||||
|
"created_at": "2025-03-20T10:00:00Z",
|
||||||
|
"updated_at": "2025-03-24T10:00:00Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"code": 400,
|
||||||
|
"msg": "نام گیاه الزامی است.",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"code": 503,
|
||||||
|
"msg": "سرویس API هنوز پیادهسازی نشده است.",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "گوجهفرنگی",
|
||||||
|
"light": "آفتاب کامل",
|
||||||
|
"watering": "منظم، هفتهای ۲ تا ۳ بار",
|
||||||
|
"soil": "لومی، غنی از مواد آلی",
|
||||||
|
"temperature": "۲۰ تا ۳۰ درجه سانتیگراد",
|
||||||
|
"planting_season": "بهار",
|
||||||
|
"harvest_time": "۷۰ تا ۹۰ روز پس از کاشت",
|
||||||
|
"spacing": "۴۵ تا ۶۰ سانتیمتر",
|
||||||
|
"fertilizer": "کود NPK متعادل",
|
||||||
|
"created_at": "2025-03-20T10:00:00Z",
|
||||||
|
"updated_at": "2025-03-24T10:00:00Z"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"status": "success",
|
||||||
|
"service": "ai",
|
||||||
|
"path": "/predict",
|
||||||
|
"result": {
|
||||||
|
"prediction": "healthy",
|
||||||
|
"confidence": 0.97
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"content_type": "text/plain; charset=utf-8",
|
||||||
|
"body": "سلام، برای بازیابی رطوبت خاک بهتر است آبیاری صبحگاهی را تنظیم کنید."
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"code": 400,
|
||||||
|
"msg": "service_id نامعتبر است: unknown_service"
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"code": 400,
|
||||||
|
"msg": "پارامتر query الزامی است."
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"code": 400,
|
||||||
|
"msg": "برای این service_id، پارامتر user_id الزامی است."
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"code": 202,
|
||||||
|
"msg": "تسک توصیه کودهی در صف قرار گرفت.",
|
||||||
|
"data": {
|
||||||
|
"task_id": "rag-fert-123",
|
||||||
|
"status_url": "/api/rag/recommend/fertilization/rag-fert-123/status/"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"code": 400,
|
||||||
|
"msg": "پارامتر sensor_uuid الزامی است.",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"task_id": "rag-fert-123",
|
||||||
|
"status": "FAILURE",
|
||||||
|
"error": "خطا در دریافت توصیه کودهی."
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"task_id": "rag-fert-123",
|
||||||
|
"status": "PENDING",
|
||||||
|
"message": "تسک در صف یا یافت نشد."
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"task_id": "rag-fert-123",
|
||||||
|
"status": "PROGRESS",
|
||||||
|
"progress": {
|
||||||
|
"message": "در حال پردازش توصیه کودهی..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"task_id": "rag-fert-123",
|
||||||
|
"status": "SUCCESS",
|
||||||
|
"result": {
|
||||||
|
"plan": {
|
||||||
|
"npkRatio": "20-20-20",
|
||||||
|
"amountPerHectare": "150 kg/ha",
|
||||||
|
"applicationMethod": "کودآبیاری در دو نوبت",
|
||||||
|
"applicationInterval": "هر ۱۰ روز",
|
||||||
|
"reasoning": "نیتروژن و پتاسیم خاک در محدوده متوسط است و گیاه در فاز رویشی نیاز تغذیهای بالاتری دارد."
|
||||||
|
},
|
||||||
|
"raw_response": "{\"plan\":{\"npkRatio\":\"20-20-20\"}}",
|
||||||
|
"status": "completed"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"code": 202,
|
||||||
|
"msg": "تسک توصیه آبیاری در صف قرار گرفت.",
|
||||||
|
"data": {
|
||||||
|
"task_id": "rag-irr-123",
|
||||||
|
"status_url": "/api/rag/recommend/irrigation/rag-irr-123/status/"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"code": 400,
|
||||||
|
"msg": "پارامتر sensor_uuid الزامی است.",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"task_id": "rag-irr-123",
|
||||||
|
"status": "FAILURE",
|
||||||
|
"error": "خطا در دریافت توصیه آبیاری."
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"task_id": "rag-irr-123",
|
||||||
|
"status": "PENDING",
|
||||||
|
"message": "تسک در صف یا یافت نشد."
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"task_id": "rag-irr-123",
|
||||||
|
"status": "PROGRESS",
|
||||||
|
"progress": {
|
||||||
|
"message": "در حال پردازش توصیه آبیاری..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"task_id": "rag-irr-123",
|
||||||
|
"status": "SUCCESS",
|
||||||
|
"result": {
|
||||||
|
"plan": {
|
||||||
|
"frequencyPerWeek": 3,
|
||||||
|
"durationMinutes": 42,
|
||||||
|
"bestTimeOfDay": "صبح زود",
|
||||||
|
"moistureLevel": 68,
|
||||||
|
"warning": "در صورت بارش موثر، نوبت سوم این هفته را حذف کنید."
|
||||||
|
},
|
||||||
|
"raw_response": "{\"plan\":{\"frequencyPerWeek\":3,\"durationMinutes\":42}}",
|
||||||
|
"water_balance": {
|
||||||
|
"daily": [
|
||||||
|
{
|
||||||
|
"forecast_date": "2025-03-25",
|
||||||
|
"et0_mm": 4.7,
|
||||||
|
"etc_mm": 5.6,
|
||||||
|
"effective_rainfall_mm": 0.0,
|
||||||
|
"gross_irrigation_mm": 6.2,
|
||||||
|
"irrigation_timing": "06:00-08:00"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"crop_profile": {
|
||||||
|
"kc_initial": 0.6,
|
||||||
|
"kc_mid": 1.15,
|
||||||
|
"kc_end": 0.8
|
||||||
|
},
|
||||||
|
"active_kc": 1.15
|
||||||
|
},
|
||||||
|
"status": "completed"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"code": 201,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"id": 3,
|
||||||
|
"code": "soil_moisture",
|
||||||
|
"name_fa": "رطوبت خاک",
|
||||||
|
"unit": "%",
|
||||||
|
"created_at": "2025-03-24T10:00:00Z",
|
||||||
|
"action": "added"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"code": 400,
|
||||||
|
"msg": "داده نامعتبر.",
|
||||||
|
"data": {
|
||||||
|
"code": [
|
||||||
|
"This field is required."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"uuid_sensor": "550e8400-e29b-41d4-a716-446655440000",
|
||||||
|
"location_id": 12,
|
||||||
|
"soil_moisture": 45.2,
|
||||||
|
"soil_temperature": 22.5,
|
||||||
|
"soil_ph": 6.8,
|
||||||
|
"electrical_conductivity": 1.2,
|
||||||
|
"nitrogen": 30.0,
|
||||||
|
"phosphorus": 15.0,
|
||||||
|
"potassium": 20.0,
|
||||||
|
"plant_ids": [
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"created_at": "2025-03-20T10:00:00Z",
|
||||||
|
"updated_at": "2025-03-24T10:00:00Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"code": 400,
|
||||||
|
"msg": "داده نامعتبر.",
|
||||||
|
"data": {
|
||||||
|
"location_id": [
|
||||||
|
"This field is required."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"code": 404,
|
||||||
|
"msg": "location_id یافت نشد.",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"uuid_sensor": "550e8400-e29b-41d4-a716-446655440000",
|
||||||
|
"location_id": 12,
|
||||||
|
"soil_moisture": 45.2,
|
||||||
|
"soil_temperature": 22.5,
|
||||||
|
"soil_ph": 6.8,
|
||||||
|
"electrical_conductivity": 1.2,
|
||||||
|
"nitrogen": 30.0,
|
||||||
|
"phosphorus": 15.0,
|
||||||
|
"potassium": 20.0,
|
||||||
|
"plant_ids": [
|
||||||
|
1
|
||||||
|
],
|
||||||
|
"created_at": "2025-03-20T10:00:00Z",
|
||||||
|
"updated_at": "2025-03-24T10:00:00Z"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"code": 400,
|
||||||
|
"msg": "داده نامعتبر.",
|
||||||
|
"data": {
|
||||||
|
"location_id": [
|
||||||
|
"This field is required."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"code": 404,
|
||||||
|
"msg": "location_id یافت نشد.",
|
||||||
|
"data": null
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"source": "database",
|
||||||
|
"id": 12,
|
||||||
|
"lon": "51.389000",
|
||||||
|
"lat": "35.689200",
|
||||||
|
"depths": [
|
||||||
|
{
|
||||||
|
"depth_label": "0-5cm",
|
||||||
|
"bdod": 1.31,
|
||||||
|
"cec": 18.4,
|
||||||
|
"cfvo": 2.0,
|
||||||
|
"clay": 24.0,
|
||||||
|
"nitrogen": 0.18,
|
||||||
|
"ocd": 32.0,
|
||||||
|
"ocs": 4.1,
|
||||||
|
"phh2o": 7.2,
|
||||||
|
"sand": 34.0,
|
||||||
|
"silt": 42.0,
|
||||||
|
"soc": 1.6,
|
||||||
|
"wv0010": 0.31,
|
||||||
|
"wv0033": 0.22,
|
||||||
|
"wv1500": 0.11
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depth_label": "5-15cm",
|
||||||
|
"bdod": 1.35,
|
||||||
|
"cec": 17.2,
|
||||||
|
"cfvo": 2.3,
|
||||||
|
"clay": 26.0,
|
||||||
|
"nitrogen": 0.16,
|
||||||
|
"ocd": 28.0,
|
||||||
|
"ocs": 3.7,
|
||||||
|
"phh2o": 7.1,
|
||||||
|
"sand": 36.0,
|
||||||
|
"silt": 38.0,
|
||||||
|
"soc": 1.4,
|
||||||
|
"wv0010": 0.29,
|
||||||
|
"wv0033": 0.2,
|
||||||
|
"wv1500": 0.1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depth_label": "15-30cm",
|
||||||
|
"bdod": 1.39,
|
||||||
|
"cec": 15.8,
|
||||||
|
"cfvo": 2.8,
|
||||||
|
"clay": 28.0,
|
||||||
|
"nitrogen": 0.13,
|
||||||
|
"ocd": 22.0,
|
||||||
|
"ocs": 3.2,
|
||||||
|
"phh2o": 7.0,
|
||||||
|
"sand": 38.0,
|
||||||
|
"silt": 34.0,
|
||||||
|
"soc": 1.1,
|
||||||
|
"wv0010": 0.26,
|
||||||
|
"wv0033": 0.18,
|
||||||
|
"wv1500": 0.09
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"code": 202,
|
||||||
|
"msg": "تسک در صف. وضعیت را با task_id بررسی کنید.",
|
||||||
|
"data": {
|
||||||
|
"source": "task",
|
||||||
|
"task_id": "soil-task-123",
|
||||||
|
"lon": 51.389,
|
||||||
|
"lat": 35.6892,
|
||||||
|
"status_url": "/api/soil-data/tasks/soil-task-123/status/"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"code": 400,
|
||||||
|
"msg": "داده نامعتبر.",
|
||||||
|
"data": {
|
||||||
|
"lat": [
|
||||||
|
"This field is required."
|
||||||
|
],
|
||||||
|
"lon": [
|
||||||
|
"This field is required."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"source": "database",
|
||||||
|
"id": 12,
|
||||||
|
"lon": "51.389000",
|
||||||
|
"lat": "35.689200",
|
||||||
|
"depths": [
|
||||||
|
{
|
||||||
|
"depth_label": "0-5cm",
|
||||||
|
"bdod": 1.31,
|
||||||
|
"cec": 18.4,
|
||||||
|
"cfvo": 2.0,
|
||||||
|
"clay": 24.0,
|
||||||
|
"nitrogen": 0.18,
|
||||||
|
"ocd": 32.0,
|
||||||
|
"ocs": 4.1,
|
||||||
|
"phh2o": 7.2,
|
||||||
|
"sand": 34.0,
|
||||||
|
"silt": 42.0,
|
||||||
|
"soc": 1.6,
|
||||||
|
"wv0010": 0.31,
|
||||||
|
"wv0033": 0.22,
|
||||||
|
"wv1500": 0.11
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depth_label": "5-15cm",
|
||||||
|
"bdod": 1.35,
|
||||||
|
"cec": 17.2,
|
||||||
|
"cfvo": 2.3,
|
||||||
|
"clay": 26.0,
|
||||||
|
"nitrogen": 0.16,
|
||||||
|
"ocd": 28.0,
|
||||||
|
"ocs": 3.7,
|
||||||
|
"phh2o": 7.1,
|
||||||
|
"sand": 36.0,
|
||||||
|
"silt": 38.0,
|
||||||
|
"soc": 1.4,
|
||||||
|
"wv0010": 0.29,
|
||||||
|
"wv0033": 0.2,
|
||||||
|
"wv1500": 0.1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depth_label": "15-30cm",
|
||||||
|
"bdod": 1.39,
|
||||||
|
"cec": 15.8,
|
||||||
|
"cfvo": 2.8,
|
||||||
|
"clay": 28.0,
|
||||||
|
"nitrogen": 0.13,
|
||||||
|
"ocd": 22.0,
|
||||||
|
"ocs": 3.2,
|
||||||
|
"phh2o": 7.0,
|
||||||
|
"sand": 38.0,
|
||||||
|
"silt": 34.0,
|
||||||
|
"soc": 1.1,
|
||||||
|
"wv0010": 0.26,
|
||||||
|
"wv0033": 0.18,
|
||||||
|
"wv1500": 0.09
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"code": 202,
|
||||||
|
"msg": "تسک در صف. وضعیت را با task_id بررسی کنید.",
|
||||||
|
"data": {
|
||||||
|
"source": "task",
|
||||||
|
"task_id": "soil-task-123",
|
||||||
|
"lon": 51.389,
|
||||||
|
"lat": 35.6892,
|
||||||
|
"status_url": "/api/soil-data/tasks/soil-task-123/status/"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"code": 400,
|
||||||
|
"msg": "داده نامعتبر.",
|
||||||
|
"data": {
|
||||||
|
"lat": [
|
||||||
|
"A valid number is required."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"task_id": "soil-task-123",
|
||||||
|
"status": "FAILURE",
|
||||||
|
"error": "خطا در واکشی داده خاک."
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"task_id": "soil-task-123",
|
||||||
|
"status": "PENDING",
|
||||||
|
"message": "تسک در صف یا یافت نشد."
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"task_id": "soil-task-123",
|
||||||
|
"status": "PROGRESS",
|
||||||
|
"progress": {
|
||||||
|
"step": "fetch",
|
||||||
|
"percent": 60
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"task_id": "soil-task-123",
|
||||||
|
"status": "SUCCESS",
|
||||||
|
"result": {
|
||||||
|
"source": "database",
|
||||||
|
"id": 12,
|
||||||
|
"lon": "51.389000",
|
||||||
|
"lat": "35.689200",
|
||||||
|
"depths": [
|
||||||
|
{
|
||||||
|
"depth_label": "0-5cm",
|
||||||
|
"bdod": 1.31,
|
||||||
|
"cec": 18.4,
|
||||||
|
"cfvo": 2.0,
|
||||||
|
"clay": 24.0,
|
||||||
|
"nitrogen": 0.18,
|
||||||
|
"ocd": 32.0,
|
||||||
|
"ocs": 4.1,
|
||||||
|
"phh2o": 7.2,
|
||||||
|
"sand": 34.0,
|
||||||
|
"silt": 42.0,
|
||||||
|
"soc": 1.6,
|
||||||
|
"wv0010": 0.31,
|
||||||
|
"wv0033": 0.22,
|
||||||
|
"wv1500": 0.11
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depth_label": "5-15cm",
|
||||||
|
"bdod": 1.35,
|
||||||
|
"cec": 17.2,
|
||||||
|
"cfvo": 2.3,
|
||||||
|
"clay": 26.0,
|
||||||
|
"nitrogen": 0.16,
|
||||||
|
"ocd": 28.0,
|
||||||
|
"ocs": 3.7,
|
||||||
|
"phh2o": 7.1,
|
||||||
|
"sand": 36.0,
|
||||||
|
"silt": 38.0,
|
||||||
|
"soc": 1.4,
|
||||||
|
"wv0010": 0.29,
|
||||||
|
"wv0033": 0.2,
|
||||||
|
"wv1500": 0.1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depth_label": "15-30cm",
|
||||||
|
"bdod": 1.39,
|
||||||
|
"cec": 15.8,
|
||||||
|
"cfvo": 2.8,
|
||||||
|
"clay": 28.0,
|
||||||
|
"nitrogen": 0.13,
|
||||||
|
"ocd": 22.0,
|
||||||
|
"ocs": 3.2,
|
||||||
|
"phh2o": 7.0,
|
||||||
|
"sand": 38.0,
|
||||||
|
"silt": 34.0,
|
||||||
|
"soc": 1.1,
|
||||||
|
"wv0010": 0.26,
|
||||||
|
"wv0033": 0.18,
|
||||||
|
"wv1500": 0.09
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"task_id": "sample-task-123"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"task_id": "sample-task-123",
|
||||||
|
"status": "FAILURE",
|
||||||
|
"error": "Sample task failed."
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"task_id": "sample-task-123",
|
||||||
|
"status": "PENDING",
|
||||||
|
"message": "تسک در صف یا یافت نشد."
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"task_id": "sample-task-123",
|
||||||
|
"status": "PROGRESS",
|
||||||
|
"progress": {
|
||||||
|
"current": 1,
|
||||||
|
"total": 3,
|
||||||
|
"message": "در حال پردازش..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "success",
|
||||||
|
"data": {
|
||||||
|
"task_id": "sample-task-123",
|
||||||
|
"status": "SUCCESS",
|
||||||
|
"result": "done"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
import json
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from .exceptions import MockDirectoryNotFound, MockFileNotFound
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class LoadedMockResponse:
|
||||||
|
data: object
|
||||||
|
status_code: int
|
||||||
|
file_path: str
|
||||||
|
|
||||||
|
|
||||||
|
class MockLoader:
|
||||||
|
def __init__(self, base_path=None):
|
||||||
|
self.base_path = Path(base_path or Path(__file__).resolve().parent / "json")
|
||||||
|
|
||||||
|
def load(self, service_name, path, method):
|
||||||
|
mock_files = self._find_mock_files(service_name=service_name, path=path, method=method)
|
||||||
|
if not mock_files:
|
||||||
|
raise MockFileNotFound(
|
||||||
|
f"No mock file found for service='{service_name}' path='{path}' method='{method}'."
|
||||||
|
)
|
||||||
|
|
||||||
|
selected_file = sorted(mock_files, key=self._mock_file_priority)[0]
|
||||||
|
with selected_file.open("r", encoding="utf-8") as file:
|
||||||
|
return LoadedMockResponse(
|
||||||
|
data=json.load(file),
|
||||||
|
status_code=self._extract_status_code(selected_file),
|
||||||
|
file_path=str(selected_file),
|
||||||
|
)
|
||||||
|
|
||||||
|
def _find_mock_files(self, service_name, path, method):
|
||||||
|
service_root = self.base_path / service_name
|
||||||
|
directory_path = service_root / self._build_directory_path(path)
|
||||||
|
pattern = f"{method.lower()}_*.json"
|
||||||
|
|
||||||
|
if directory_path.exists() and directory_path.is_dir():
|
||||||
|
return list(directory_path.glob(pattern))
|
||||||
|
|
||||||
|
leaf_name = self._extract_leaf_name(path)
|
||||||
|
parent_directory = directory_path.parent
|
||||||
|
if parent_directory.exists() and parent_directory.is_dir():
|
||||||
|
flat_pattern = f"{leaf_name}-{method.lower()}_*.json"
|
||||||
|
flat_files = list(parent_directory.glob(flat_pattern))
|
||||||
|
if flat_files:
|
||||||
|
return flat_files
|
||||||
|
|
||||||
|
raise MockDirectoryNotFound(
|
||||||
|
f"Mock directory not found for service='{service_name}' path='{path}': {directory_path}"
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _build_directory_path(path):
|
||||||
|
normalized = str(path).strip().strip("/")
|
||||||
|
if not normalized:
|
||||||
|
return Path(".")
|
||||||
|
return Path(*normalized.split("/"))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _extract_status_code(file_path):
|
||||||
|
parts = file_path.stem.split("_")
|
||||||
|
if len(parts) < 2:
|
||||||
|
return 200
|
||||||
|
try:
|
||||||
|
return int(parts[1])
|
||||||
|
except ValueError:
|
||||||
|
return 200
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _extract_leaf_name(path):
|
||||||
|
normalized = str(path).strip().strip("/")
|
||||||
|
if not normalized:
|
||||||
|
return ""
|
||||||
|
return normalized.split("/")[-1]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _mock_file_priority(file_path):
|
||||||
|
stem = file_path.stem.lower()
|
||||||
|
status_code = MockLoader._extract_status_code(file_path)
|
||||||
|
keyword_rank = 2
|
||||||
|
if "success" in stem:
|
||||||
|
keyword_rank = 0
|
||||||
|
elif "stream" in stem:
|
||||||
|
keyword_rank = 0
|
||||||
|
elif "pending" in stem or "progress" in stem:
|
||||||
|
keyword_rank = 1
|
||||||
|
return (status_code >= 400, keyword_rank, stem)
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user