import json from pathlib import Path BASE_DIR = Path(__file__).resolve().parents[1] MOCK_DIR = BASE_DIR / "json" / "mock_data" def queue_response(message, task_id, status_url, **extra): data = { "task_id": task_id, "status_url": status_url, } data.update(extra) return { "code": 202, "msg": message, "data": data, } def ok_response(data, message="success", code=200): return { "code": code, "msg": message, "data": data, } def error_response(code, message, data=None): return { "code": code, "msg": message, "data": data, } def task_pending(task_id): return ok_response( { "task_id": task_id, "status": "PENDING", "message": "تسک در صف یا یافت نشد.", } ) def task_progress(task_id, progress): return ok_response( { "task_id": task_id, "status": "PROGRESS", "progress": progress, } ) def task_success(task_id, result): return ok_response( { "task_id": task_id, "status": "SUCCESS", "result": result, } ) def task_failure(task_id, error): return ok_response( { "task_id": task_id, "status": "FAILURE", "error": error, } ) PLANT = { "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", } IRRIGATION_METHOD = { "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", } SOIL_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, }, ] SOIL_LOCATION = { "source": "database", "id": 12, "lon": "51.389000", "lat": "35.689200", "depths": SOIL_DEPTHS, } SOIL_TASK_DATA = { "source": "task", "task_id": "soil-task-123", "lon": 51.389, "lat": 35.6892, "status_url": "/api/soil-data/tasks/soil-task-123/status/", } SENSOR_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", } SENSOR_PARAMETER = { "id": 3, "code": "soil_moisture", "name_fa": "رطوبت خاک", "unit": "%", "created_at": "2025-03-24T10:00:00Z", "action": "added", } IRRIGATION_RECOMMENDATION_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", } FERTILIZATION_RECOMMENDATION_RESULT = { "plan": { "npkRatio": "20-20-20", "amountPerHectare": "150 kg/ha", "applicationMethod": "کودآبیاری در دو نوبت", "applicationInterval": "هر ۱۰ روز", "reasoning": "نیتروژن و پتاسیم خاک در محدوده متوسط است و گیاه در فاز رویشی نیاز تغذیه‌ای بالاتری دارد.", }, "raw_response": "{\"plan\":{\"npkRatio\":\"20-20-20\"}}", "status": "completed", } DASHBOARD_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", } ] }, }, } TASK_PROGRESS = {"current": 1, "total": 3, "message": "در حال پردازش..."} RAG_STREAM_SUCCESS = { "content_type": "text/plain; charset=utf-8", "body": "سلام، برای بازیابی رطوبت خاک بهتر است آبیاری صبح‌گاهی را تنظیم کنید.", } index = [] def register(path, method, api_path, status_code, description, payload): full_path = MOCK_DIR / path full_path.parent.mkdir(parents=True, exist_ok=True) full_path.write_text( json.dumps(payload, ensure_ascii=False, indent=2) + "\n", encoding="utf-8", ) index.append( { "method": method, "path": api_path, "status_code": status_code, "description": description, "file": str(Path("json/mock_data") / path), } ) def main(): register( "dashboard-data/generate/post_202.json", "POST", "/api/dashboard-data/generate/", 202, "Dashboard data task queued", queue_response( "dashboard task queued", "dashboard-task-123", "/api/dashboard-data/dashboard-task-123/status/", ), ) register( "dashboard-data/generate/post_400.json", "POST", "/api/dashboard-data/generate/", 400, "Missing sensor_id", error_response(400, "پارامتر sensor_id الزامی است.", None), ) register( "dashboard-data/status/get_200_pending.json", "GET", "/api/dashboard-data/{task_id}/status/", 200, "Pending dashboard task", task_pending("dashboard-task-123"), ) register( "dashboard-data/status/get_200_progress.json", "GET", "/api/dashboard-data/{task_id}/status/", 200, "Dashboard task in progress", task_progress( "dashboard-task-123", {"current": 5, "total": 15, "card": "sensorValuesList", "message": "processing sensorValuesList"}, ), ) register( "dashboard-data/status/get_200_success.json", "GET", "/api/dashboard-data/{task_id}/status/", 200, "Successful dashboard task", task_success("dashboard-task-123", DASHBOARD_RESULT), ) register( "dashboard-data/status/get_200_failure.json", "GET", "/api/dashboard-data/{task_id}/status/", 200, "Failed dashboard task", task_failure("dashboard-task-123", "خطا در ساخت کارت‌های داشبورد."), ) register( "fertilization/recommend/post_202.json", "POST", "/api/fertilization/recommend/", 202, "Fertilization task queued", queue_response( "تسک توصیه کودهی در صف قرار گرفت.", "fert-task-123", "/api/fertilization/recommend/fert-task-123/status/", ), ) register( "fertilization/recommend/post_400.json", "POST", "/api/fertilization/recommend/", 400, "Validation error", error_response(400, "داده نامعتبر.", {"sensor_uuid": ["This field is required."]}), ) for name, payload in { "pending": task_pending("fert-task-123"), "progress": task_progress("fert-task-123", {"message": "در حال پردازش توصیه کودهی..."}), "success": task_success("fert-task-123", FERTILIZATION_RECOMMENDATION_RESULT), "failure": task_failure("fert-task-123", "خطا در دریافت توصیه کودهی."), }.items(): register( f"fertilization/status/get_200_{name}.json", "GET", "/api/fertilization/recommend/{task_id}/status/", 200, f"Fertilization status {name}", payload, ) register( "irrigation/methods/get_200.json", "GET", "/api/irrigation/", 200, "List irrigation methods", ok_response([IRRIGATION_METHOD]), ) register( "irrigation/methods/post_201.json", "POST", "/api/irrigation/", 201, "Create irrigation method", ok_response(IRRIGATION_METHOD, code=201), ) register( "irrigation/methods/post_400.json", "POST", "/api/irrigation/", 400, "Irrigation create validation error", error_response(400, "داده نامعتبر.", {"name": ["This field is required."]}), ) register( "irrigation/recommend/post_202.json", "POST", "/api/irrigation/recommend/", 202, "Irrigation recommendation task queued", queue_response( "تسک توصیه آبیاری در صف قرار گرفت.", "irr-task-123", "/api/irrigation/recommend/irr-task-123/status/", ), ) register( "irrigation/recommend/post_400.json", "POST", "/api/irrigation/recommend/", 400, "Irrigation recommendation validation error", error_response(400, "داده نامعتبر.", {"sensor_uuid": ["This field is required."]}), ) for name, payload in { "pending": task_pending("irr-task-123"), "progress": task_progress("irr-task-123", {"message": "در حال پردازش توصیه آبیاری..."}), "success": task_success("irr-task-123", IRRIGATION_RECOMMENDATION_RESULT), "failure": task_failure("irr-task-123", "خطا در دریافت توصیه آبیاری."), }.items(): register( f"irrigation/recommend/status/get_200_{name}.json", "GET", "/api/irrigation/recommend/{task_id}/status/", 200, f"Irrigation recommendation status {name}", payload, ) for method, success_code in (("get", 200), ("put", 200), ("patch", 200)): register( f"irrigation/method-detail/{method}_{success_code}.json", method.upper(), "/api/irrigation/{pk}/", success_code, f"Irrigation method {method} success", ok_response(IRRIGATION_METHOD, code=success_code), ) if method in {"put", "patch"}: register( f"irrigation/method-detail/{method}_400.json", method.upper(), "/api/irrigation/{pk}/", 400, f"Irrigation method {method} validation error", error_response(400, "داده نامعتبر.", {"name": ["This field may not be blank."]}), ) register( f"irrigation/method-detail/{method}_404.json", method.upper(), "/api/irrigation/{pk}/", 404, f"Irrigation method {method} not found", error_response(404, "روش آبیاری یافت نشد.", None), ) register( "irrigation/method-detail/delete_200.json", "DELETE", "/api/irrigation/{pk}/", 200, "Delete irrigation method", error_response(200, "روش آبیاری با موفقیت حذف شد.", None), ) register( "irrigation/method-detail/delete_404.json", "DELETE", "/api/irrigation/{pk}/", 404, "Delete irrigation method not found", error_response(404, "روش آبیاری یافت نشد.", None), ) register( "soil-data/get_200_database.json", "GET", "/api/soil-data/", 200, "Soil data served from database", ok_response(SOIL_LOCATION), ) register( "soil-data/get_202_queued.json", "GET", "/api/soil-data/", 202, "Soil data fetch task queued", { "code": 202, "msg": "تسک در صف. وضعیت را با task_id بررسی کنید.", "data": SOIL_TASK_DATA, }, ) register( "soil-data/get_400.json", "GET", "/api/soil-data/", 400, "Soil data validation error", error_response(400, "داده نامعتبر.", {"lat": ["This field is required."], "lon": ["This field is required."]}), ) register( "soil-data/post_200_database.json", "POST", "/api/soil-data/", 200, "Soil data POST served from database", ok_response(SOIL_LOCATION), ) register( "soil-data/post_202_queued.json", "POST", "/api/soil-data/", 202, "Soil data POST task queued", { "code": 202, "msg": "تسک در صف. وضعیت را با task_id بررسی کنید.", "data": SOIL_TASK_DATA, }, ) register( "soil-data/post_400.json", "POST", "/api/soil-data/", 400, "Soil data POST validation error", error_response(400, "داده نامعتبر.", {"lat": ["A valid number is required."]}), ) for name, payload in { "pending": task_pending("soil-task-123"), "progress": task_progress("soil-task-123", {"step": "fetch", "percent": 60}), "success": task_success("soil-task-123", SOIL_LOCATION | {"source": "database"}), "failure": task_failure("soil-task-123", "خطا در واکشی داده خاک."), }.items(): register( f"soil-data/status/get_200_{name}.json", "GET", "/api/soil-data/tasks/{task_id}/status/", 200, f"Soil task status {name}", payload, ) register( "plant/list-get_200.json", "GET", "/api/plants/", 200, "List plants", ok_response([PLANT]), ) register( "plant/create-post_201.json", "POST", "/api/plants/", 201, "Create plant", ok_response(PLANT, code=201), ) register( "plant/create-post_400.json", "POST", "/api/plants/", 400, "Plant create validation error", error_response(400, "داده نامعتبر.", {"name": ["This field is required."]}), ) for method in ("get", "put", "patch"): register( f"plant/detail-{method}_200.json", method.upper(), "/api/plants/{pk}/", 200, f"Plant detail {method} success", ok_response(PLANT), ) if method in {"put", "patch"}: register( f"plant/detail-{method}_400.json", method.upper(), "/api/plants/{pk}/", 400, f"Plant detail {method} validation error", error_response(400, "داده نامعتبر.", {"name": ["This field may not be blank."]}), ) register( f"plant/detail-{method}_404.json", method.upper(), "/api/plants/{pk}/", 404, f"Plant detail {method} not found", error_response(404, "گیاه یافت نشد.", None), ) register( "plant/detail-delete_200.json", "DELETE", "/api/plants/{pk}/", 200, "Delete plant success", error_response(200, "گیاه با موفقیت حذف شد.", None), ) register( "plant/detail-delete_404.json", "DELETE", "/api/plants/{pk}/", 404, "Delete plant not found", error_response(404, "گیاه یافت نشد.", None), ) register( "plant/fetch-info-post_200.json", "POST", "/api/plants/fetch-info/", 200, "Fetch plant info success", ok_response(PLANT), ) register( "plant/fetch-info-post_400.json", "POST", "/api/plants/fetch-info/", 400, "Fetch plant info missing name", error_response(400, "نام گیاه الزامی است.", None), ) register( "plant/fetch-info-post_503.json", "POST", "/api/plants/fetch-info/", 503, "Fetch plant info service unavailable", error_response(503, "سرویس API هنوز پیاده‌سازی نشده است.", None), ) register( "rag/chat-post_200_stream.json", "POST", "/api/rag/chat/", 200, "RAG chat streaming response", RAG_STREAM_SUCCESS, ) register( "rag/chat-post_400_missing_query.json", "POST", "/api/rag/chat/", 400, "Missing query", {"code": 400, "msg": "پارامتر query الزامی است."}, ) register( "rag/chat-post_400_invalid_service.json", "POST", "/api/rag/chat/", 400, "Invalid service id", {"code": 400, "msg": "service_id نامعتبر است: unknown_service"}, ) register( "rag/chat-post_400_missing_user.json", "POST", "/api/rag/chat/", 400, "Missing user_id for service", {"code": 400, "msg": "برای این service_id، پارامتر user_id الزامی است."}, ) register( "rag/irrigation/post_202.json", "POST", "/api/rag/recommend/irrigation/", 202, "RAG irrigation task queued", queue_response( "تسک توصیه آبیاری در صف قرار گرفت.", "rag-irr-123", "/api/rag/recommend/irrigation/rag-irr-123/status/", ), ) register( "rag/irrigation/post_400.json", "POST", "/api/rag/recommend/irrigation/", 400, "RAG irrigation validation error", error_response(400, "پارامتر sensor_uuid الزامی است.", None), ) for name, payload in { "pending": task_pending("rag-irr-123"), "progress": task_progress("rag-irr-123", {"message": "در حال پردازش توصیه آبیاری..."}), "success": task_success("rag-irr-123", IRRIGATION_RECOMMENDATION_RESULT), "failure": task_failure("rag-irr-123", "خطا در دریافت توصیه آبیاری."), }.items(): register( f"rag/irrigation/status/get_200_{name}.json", "GET", "/api/rag/recommend/irrigation/{task_id}/status/", 200, f"RAG irrigation status {name}", payload, ) register( "rag/fertilization/post_202.json", "POST", "/api/rag/recommend/fertilization/", 202, "RAG fertilization task queued", queue_response( "تسک توصیه کودهی در صف قرار گرفت.", "rag-fert-123", "/api/rag/recommend/fertilization/rag-fert-123/status/", ), ) register( "rag/fertilization/post_400.json", "POST", "/api/rag/recommend/fertilization/", 400, "RAG fertilization validation error", error_response(400, "پارامتر sensor_uuid الزامی است.", None), ) for name, payload in { "pending": task_pending("rag-fert-123"), "progress": task_progress("rag-fert-123", {"message": "در حال پردازش توصیه کودهی..."}), "success": task_success("rag-fert-123", FERTILIZATION_RECOMMENDATION_RESULT), "failure": task_failure("rag-fert-123", "خطا در دریافت توصیه کودهی."), }.items(): register( f"rag/fertilization/status/get_200_{name}.json", "GET", "/api/rag/recommend/fertilization/{task_id}/status/", 200, f"RAG fertilization status {name}", payload, ) for method in ("put", "patch"): register( f"sensor-data/update-{method}_200.json", method.upper(), "/api/sensor-data/{uuid_sensor}/", 200, f"Sensor update {method} success", ok_response(SENSOR_DATA), ) register( f"sensor-data/update-{method}_400.json", method.upper(), "/api/sensor-data/{uuid_sensor}/", 400, f"Sensor update {method} validation error", error_response(400, "داده نامعتبر.", {"location_id": ["This field is required."]}), ) register( f"sensor-data/update-{method}_404.json", method.upper(), "/api/sensor-data/{uuid_sensor}/", 404, f"Sensor update {method} location not found", error_response(404, "location_id یافت نشد.", None), ) register( "sensor-data/parameters-post_201.json", "POST", "/api/sensor-data/parameters/", 201, "Create sensor parameter", ok_response(SENSOR_PARAMETER, code=201), ) register( "sensor-data/parameters-post_400.json", "POST", "/api/sensor-data/parameters/", 400, "Sensor parameter validation error", error_response(400, "داده نامعتبر.", {"code": ["This field is required."]}), ) register( "tasks/post_200.json", "POST", "/api/tasks/", 200, "Task trigger success", ok_response({"task_id": "sample-task-123"}), ) for name, payload in { "pending": task_pending("sample-task-123"), "progress": task_progress("sample-task-123", TASK_PROGRESS), "success": task_success("sample-task-123", "done"), "failure": task_failure("sample-task-123", "Sample task failed."), }.items(): register( f"tasks/status/get_200_{name}.json", "GET", "/api/tasks/{task_id}/status/", 200, f"Task status {name}", payload, ) (MOCK_DIR / "index.json").write_text( json.dumps(index, ensure_ascii=False, indent=2) + "\n", encoding="utf-8", ) if __name__ == "__main__": main()