diff --git a/.idea/RSI.iml b/.idea/RSI.iml index cfcee21..a9f91e1 100644 --- a/.idea/RSI.iml +++ b/.idea/RSI.iml @@ -19,7 +19,7 @@ - + diff --git a/RSI/__pycache__/__init__.cpython-312.pyc b/RSI/__pycache__/__init__.cpython-312.pyc index de388e4..611df2b 100644 Binary files a/RSI/__pycache__/__init__.cpython-312.pyc and b/RSI/__pycache__/__init__.cpython-312.pyc differ diff --git a/RSI/__pycache__/settings.cpython-312.pyc b/RSI/__pycache__/settings.cpython-312.pyc index 4e720b2..739753f 100644 Binary files a/RSI/__pycache__/settings.cpython-312.pyc and b/RSI/__pycache__/settings.cpython-312.pyc differ diff --git a/RSI/__pycache__/urls.cpython-312.pyc b/RSI/__pycache__/urls.cpython-312.pyc index a8bddf0..9559074 100644 Binary files a/RSI/__pycache__/urls.cpython-312.pyc and b/RSI/__pycache__/urls.cpython-312.pyc differ diff --git a/RSI/__pycache__/wsgi.cpython-312.pyc b/RSI/__pycache__/wsgi.cpython-312.pyc index e72caa2..852a173 100644 Binary files a/RSI/__pycache__/wsgi.cpython-312.pyc and b/RSI/__pycache__/wsgi.cpython-312.pyc differ diff --git a/__pycache__/helpers.cpython-312.pyc b/__pycache__/helpers.cpython-312.pyc index 4fbe9c7..65fbef3 100644 Binary files a/__pycache__/helpers.cpython-312.pyc and b/__pycache__/helpers.cpython-312.pyc differ diff --git a/app/__pycache__/__init__.cpython-312.pyc b/app/__pycache__/__init__.cpython-312.pyc index e585a3f..b478ea6 100644 Binary files a/app/__pycache__/__init__.cpython-312.pyc and b/app/__pycache__/__init__.cpython-312.pyc differ diff --git a/app/__pycache__/admin.cpython-312.pyc b/app/__pycache__/admin.cpython-312.pyc index 6ba60a1..0aa4f86 100644 Binary files a/app/__pycache__/admin.cpython-312.pyc and b/app/__pycache__/admin.cpython-312.pyc differ diff --git a/app/__pycache__/apps.cpython-312.pyc b/app/__pycache__/apps.cpython-312.pyc index 71dcad5..d544cfb 100644 Binary files a/app/__pycache__/apps.cpython-312.pyc and b/app/__pycache__/apps.cpython-312.pyc differ diff --git a/app/__pycache__/cityandprovince.cpython-312.pyc b/app/__pycache__/cityandprovince.cpython-312.pyc index 34938e6..c4c8b2a 100644 Binary files a/app/__pycache__/cityandprovince.cpython-312.pyc and b/app/__pycache__/cityandprovince.cpython-312.pyc differ diff --git a/app/__pycache__/excel_processing.cpython-312.pyc b/app/__pycache__/excel_processing.cpython-312.pyc index b8db971..b2bb301 100644 Binary files a/app/__pycache__/excel_processing.cpython-312.pyc and b/app/__pycache__/excel_processing.cpython-312.pyc differ diff --git a/app/__pycache__/filtersets.cpython-312.pyc b/app/__pycache__/filtersets.cpython-312.pyc index dfe4609..d3362a4 100644 Binary files a/app/__pycache__/filtersets.cpython-312.pyc and b/app/__pycache__/filtersets.cpython-312.pyc differ diff --git a/app/__pycache__/helper.cpython-312.pyc b/app/__pycache__/helper.cpython-312.pyc index c93382b..f224d6b 100644 Binary files a/app/__pycache__/helper.cpython-312.pyc and b/app/__pycache__/helper.cpython-312.pyc differ diff --git a/app/__pycache__/helper_excel.cpython-312.pyc b/app/__pycache__/helper_excel.cpython-312.pyc index b83ed7b..0242cd0 100644 Binary files a/app/__pycache__/helper_excel.cpython-312.pyc and b/app/__pycache__/helper_excel.cpython-312.pyc differ diff --git a/app/__pycache__/models.cpython-312.pyc b/app/__pycache__/models.cpython-312.pyc index b996c78..ff9e92f 100644 Binary files a/app/__pycache__/models.cpython-312.pyc and b/app/__pycache__/models.cpython-312.pyc differ diff --git a/app/__pycache__/scripts.cpython-312.pyc b/app/__pycache__/scripts.cpython-312.pyc index 8ddf365..3e18e90 100644 Binary files a/app/__pycache__/scripts.cpython-312.pyc and b/app/__pycache__/scripts.cpython-312.pyc differ diff --git a/app/__pycache__/serializers.cpython-312.pyc b/app/__pycache__/serializers.cpython-312.pyc index dcd9487..99fd1f8 100644 Binary files a/app/__pycache__/serializers.cpython-312.pyc and b/app/__pycache__/serializers.cpython-312.pyc differ diff --git a/app/__pycache__/urls.cpython-312.pyc b/app/__pycache__/urls.cpython-312.pyc index 928ccf6..48d8983 100644 Binary files a/app/__pycache__/urls.cpython-312.pyc and b/app/__pycache__/urls.cpython-312.pyc differ diff --git a/app/__pycache__/views.cpython-312.pyc b/app/__pycache__/views.cpython-312.pyc index 95968d5..40eceb7 100644 Binary files a/app/__pycache__/views.cpython-312.pyc and b/app/__pycache__/views.cpython-312.pyc differ diff --git a/app/helper.py b/app/helper.py index fd76876..f5b93b5 100644 --- a/app/helper.py +++ b/app/helper.py @@ -177,3 +177,77 @@ class SSLAdapter(HTTPAdapter): self.context = create_urllib3_context() self.context.options |= 0x4 # OP_LEGACY_SERVER_CONNECT super().__init__(*args, **kwargs) + + + + + +from datetime import datetime, timedelta +from django.utils import timezone + + +def apply_date_filter(queryset, date_filter): + if not date_filter: + return queryset + + field = date_filter.get("field", "Date") + filter_type = date_filter.get("type") + value = date_filter.get("value") + + now = timezone.now() + + if filter_type == "today": + start = now.replace(hour=0, minute=0, second=0, microsecond=0) + end = start + timedelta(days=1) + return queryset.filter( + **{f"{field}__gte": start, f"{field}__lt": end} + ) + + if filter_type == "yesterday": + start = (now - timedelta(days=1)).replace( + hour=0, minute=0, second=0, microsecond=0 + ) + end = start + timedelta(days=1) + return queryset.filter( + **{f"{field}__gte": start, f"{field}__lt": end} + ) + + if filter_type == "last_n_days" and value: + start = now - timedelta(days=int(value)) + return queryset.filter(**{f"{field}__gte": start}) + + if filter_type == "this_week": + start = now - timedelta(days=now.weekday()) + start = start.replace(hour=0, minute=0, second=0, microsecond=0) + return queryset.filter(**{f"{field}__gte": start}) + + if filter_type == "this_month": + start = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0) + return queryset.filter(**{f"{field}__gte": start}) + + if filter_type == "last_n_month" and value: + start = now + for _ in range(int(value)): + start = (start.replace(day=1) - timedelta(days=1)).replace(day=1) + start = start.replace(hour=0, minute=0, second=0, microsecond=0) + return queryset.filter(**{f"{field}__gte": start}) + + if filter_type == "this_year": + start = now.replace( + month=1, day=1, hour=0, minute=0, second=0, microsecond=0 + ) + return queryset.filter(**{f"{field}__gte": start}) + + if filter_type == "last_n_year" and value: + start = now.replace( + year=now.year - int(value), + month=1, + day=1, + hour=0, + minute=0, + second=0, + microsecond=0 + ) + return queryset.filter(**{f"{field}__gte": start}) + + return queryset \ No newline at end of file diff --git a/app/migrations/__pycache__/0001_initial.cpython-312.pyc b/app/migrations/__pycache__/0001_initial.cpython-312.pyc index a5ddbdd..cc0a6f8 100644 Binary files a/app/migrations/__pycache__/0001_initial.cpython-312.pyc and b/app/migrations/__pycache__/0001_initial.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0002_remove_poultry_allowinsert_and_more.cpython-312.pyc b/app/migrations/__pycache__/0002_remove_poultry_allowinsert_and_more.cpython-312.pyc index 5c823a8..3b3176b 100644 Binary files a/app/migrations/__pycache__/0002_remove_poultry_allowinsert_and_more.cpython-312.pyc and b/app/migrations/__pycache__/0002_remove_poultry_allowinsert_and_more.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0003_poultry_allowinsert_poultry_allowupdate_and_more.cpython-312.pyc b/app/migrations/__pycache__/0003_poultry_allowinsert_poultry_allowupdate_and_more.cpython-312.pyc index 05a9590..21c61a7 100644 Binary files a/app/migrations/__pycache__/0003_poultry_allowinsert_poultry_allowupdate_and_more.cpython-312.pyc and b/app/migrations/__pycache__/0003_poultry_allowinsert_poultry_allowupdate_and_more.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0004_poultryhatching_date_poultryhatching_hatchingage.cpython-312.pyc b/app/migrations/__pycache__/0004_poultryhatching_date_poultryhatching_hatchingage.cpython-312.pyc index cada48f..72a6df4 100644 Binary files a/app/migrations/__pycache__/0004_poultryhatching_date_poultryhatching_hatchingage.cpython-312.pyc and b/app/migrations/__pycache__/0004_poultryhatching_date_poultryhatching_hatchingage.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0005_remove_poultryhatching_basehatchingcount_and_more.cpython-312.pyc b/app/migrations/__pycache__/0005_remove_poultryhatching_basehatchingcount_and_more.cpython-312.pyc index 007b94d..95a40f5 100644 Binary files a/app/migrations/__pycache__/0005_remove_poultryhatching_basehatchingcount_and_more.cpython-312.pyc and b/app/migrations/__pycache__/0005_remove_poultryhatching_basehatchingcount_and_more.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0006_poultryhatching_basehatchingcount_and_more.cpython-312.pyc b/app/migrations/__pycache__/0006_poultryhatching_basehatchingcount_and_more.cpython-312.pyc index 8ddd843..48ded36 100644 Binary files a/app/migrations/__pycache__/0006_poultryhatching_basehatchingcount_and_more.cpython-312.pyc and b/app/migrations/__pycache__/0006_poultryhatching_basehatchingcount_and_more.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0007_transportingchickendetail.cpython-312.pyc b/app/migrations/__pycache__/0007_transportingchickendetail.cpython-312.pyc index aa50d21..53fdaf4 100644 Binary files a/app/migrations/__pycache__/0007_transportingchickendetail.cpython-312.pyc and b/app/migrations/__pycache__/0007_transportingchickendetail.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0008_transportingchickendetail_certid_and_more.cpython-312.pyc b/app/migrations/__pycache__/0008_transportingchickendetail_certid_and_more.cpython-312.pyc index 94f1302..b7b3509 100644 Binary files a/app/migrations/__pycache__/0008_transportingchickendetail_certid_and_more.cpython-312.pyc and b/app/migrations/__pycache__/0008_transportingchickendetail_certid_and_more.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0009_transportingchickendetail_broilerflockrequestid_and_more.cpython-312.pyc b/app/migrations/__pycache__/0009_transportingchickendetail_broilerflockrequestid_and_more.cpython-312.pyc index bb9feee..5a671f7 100644 Binary files a/app/migrations/__pycache__/0009_transportingchickendetail_broilerflockrequestid_and_more.cpython-312.pyc and b/app/migrations/__pycache__/0009_transportingchickendetail_broilerflockrequestid_and_more.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0010_transportingchickendetail_province_and_more.cpython-312.pyc b/app/migrations/__pycache__/0010_transportingchickendetail_province_and_more.cpython-312.pyc index f2d5bce..48525e3 100644 Binary files a/app/migrations/__pycache__/0010_transportingchickendetail_province_and_more.cpython-312.pyc and b/app/migrations/__pycache__/0010_transportingchickendetail_province_and_more.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0011_poultryhatching_pedigreename.cpython-312.pyc b/app/migrations/__pycache__/0011_poultryhatching_pedigreename.cpython-312.pyc index 2595756..bab4021 100644 Binary files a/app/migrations/__pycache__/0011_poultryhatching_pedigreename.cpython-312.pyc and b/app/migrations/__pycache__/0011_poultryhatching_pedigreename.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0012_transportingchickendetail_age.cpython-312.pyc b/app/migrations/__pycache__/0012_transportingchickendetail_age.cpython-312.pyc index 1e4e0ac..48bdaa1 100644 Binary files a/app/migrations/__pycache__/0012_transportingchickendetail_age.cpython-312.pyc and b/app/migrations/__pycache__/0012_transportingchickendetail_age.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0013_poultryhatching_leftover.cpython-312.pyc b/app/migrations/__pycache__/0013_poultryhatching_leftover.cpython-312.pyc index 2cb2c8a..dbc8cf8 100644 Binary files a/app/migrations/__pycache__/0013_poultryhatching_leftover.cpython-312.pyc and b/app/migrations/__pycache__/0013_poultryhatching_leftover.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0014_poultry_locationnamecity_and_more.cpython-312.pyc b/app/migrations/__pycache__/0014_poultry_locationnamecity_and_more.cpython-312.pyc index ede32fd..f7be85f 100644 Binary files a/app/migrations/__pycache__/0014_poultry_locationnamecity_and_more.cpython-312.pyc and b/app/migrations/__pycache__/0014_poultry_locationnamecity_and_more.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0015_hatching_transportingdetail.cpython-312.pyc b/app/migrations/__pycache__/0015_hatching_transportingdetail.cpython-312.pyc index a182fbd..8832884 100644 Binary files a/app/migrations/__pycache__/0015_hatching_transportingdetail.cpython-312.pyc and b/app/migrations/__pycache__/0015_hatching_transportingdetail.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0016_remove_transportingdetail_certid_and_more.cpython-312.pyc b/app/migrations/__pycache__/0016_remove_transportingdetail_certid_and_more.cpython-312.pyc index 9c0435b..15ff979 100644 Binary files a/app/migrations/__pycache__/0016_remove_transportingdetail_certid_and_more.cpython-312.pyc and b/app/migrations/__pycache__/0016_remove_transportingdetail_certid_and_more.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0017_hatching_archivedate.cpython-312.pyc b/app/migrations/__pycache__/0017_hatching_archivedate.cpython-312.pyc index 41413e3..342ae79 100644 Binary files a/app/migrations/__pycache__/0017_hatching_archivedate.cpython-312.pyc and b/app/migrations/__pycache__/0017_hatching_archivedate.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0018_remove_hatching_capacityfemale.cpython-312.pyc b/app/migrations/__pycache__/0018_remove_hatching_capacityfemale.cpython-312.pyc index be72a4f..b8ca5ac 100644 Binary files a/app/migrations/__pycache__/0018_remove_hatching_capacityfemale.cpython-312.pyc and b/app/migrations/__pycache__/0018_remove_hatching_capacityfemale.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0019_hatching_capacityfemale.cpython-312.pyc b/app/migrations/__pycache__/0019_hatching_capacityfemale.cpython-312.pyc index a832a59..a55f788 100644 Binary files a/app/migrations/__pycache__/0019_hatching_capacityfemale.cpython-312.pyc and b/app/migrations/__pycache__/0019_hatching_capacityfemale.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0020_killhouse.cpython-312.pyc b/app/migrations/__pycache__/0020_killhouse.cpython-312.pyc index 806a0f7..0caf569 100644 Binary files a/app/migrations/__pycache__/0020_killhouse.cpython-312.pyc and b/app/migrations/__pycache__/0020_killhouse.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0021_hatching_killingave_transportingdetail_out_and_more.cpython-312.pyc b/app/migrations/__pycache__/0021_hatching_killingave_transportingdetail_out_and_more.cpython-312.pyc index 358084b..60e9905 100644 Binary files a/app/migrations/__pycache__/0021_hatching_killingave_transportingdetail_out_and_more.cpython-312.pyc and b/app/migrations/__pycache__/0021_hatching_killingave_transportingdetail_out_and_more.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0022_alter_hatching_killingave.cpython-312.pyc b/app/migrations/__pycache__/0022_alter_hatching_killingave.cpython-312.pyc index 4dce39a..93e93fe 100644 Binary files a/app/migrations/__pycache__/0022_alter_hatching_killingave.cpython-312.pyc and b/app/migrations/__pycache__/0022_alter_hatching_killingave.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0023_killhouse_cityid_killhouse_provinceid.cpython-312.pyc b/app/migrations/__pycache__/0023_killhouse_cityid_killhouse_provinceid.cpython-312.pyc index 9899198..eaa4f08 100644 Binary files a/app/migrations/__pycache__/0023_killhouse_cityid_killhouse_provinceid.cpython-312.pyc and b/app/migrations/__pycache__/0023_killhouse_cityid_killhouse_provinceid.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0024_poultry_city_poultry_province.cpython-312.pyc b/app/migrations/__pycache__/0024_poultry_city_poultry_province.cpython-312.pyc index 4426600..bdc3cb8 100644 Binary files a/app/migrations/__pycache__/0024_poultry_city_poultry_province.cpython-312.pyc and b/app/migrations/__pycache__/0024_poultry_city_poultry_province.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0025_delete_transportingdetail.cpython-312.pyc b/app/migrations/__pycache__/0025_delete_transportingdetail.cpython-312.pyc index c88e24b..6a3faba 100644 Binary files a/app/migrations/__pycache__/0025_delete_transportingdetail.cpython-312.pyc and b/app/migrations/__pycache__/0025_delete_transportingdetail.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0026_transportingdetail.cpython-312.pyc b/app/migrations/__pycache__/0026_transportingdetail.cpython-312.pyc index 662eb62..2645514 100644 Binary files a/app/migrations/__pycache__/0026_transportingdetail.cpython-312.pyc and b/app/migrations/__pycache__/0026_transportingdetail.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0027_hatching_samasat_discharge_percentage_and_more.cpython-312.pyc b/app/migrations/__pycache__/0027_hatching_samasat_discharge_percentage_and_more.cpython-312.pyc index b75b06e..fb688a6 100644 Binary files a/app/migrations/__pycache__/0027_hatching_samasat_discharge_percentage_and_more.cpython-312.pyc and b/app/migrations/__pycache__/0027_hatching_samasat_discharge_percentage_and_more.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0028_hatching_goodsum.cpython-312.pyc b/app/migrations/__pycache__/0028_hatching_goodsum.cpython-312.pyc index 0dbf14a..8955e83 100644 Binary files a/app/migrations/__pycache__/0028_hatching_goodsum.cpython-312.pyc and b/app/migrations/__pycache__/0028_hatching_goodsum.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0029_apkinfo.cpython-312.pyc b/app/migrations/__pycache__/0029_apkinfo.cpython-312.pyc index 13e1131..be52a52 100644 Binary files a/app/migrations/__pycache__/0029_apkinfo.cpython-312.pyc and b/app/migrations/__pycache__/0029_apkinfo.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0030_transportcarcassdetail.cpython-312.pyc b/app/migrations/__pycache__/0030_transportcarcassdetail.cpython-312.pyc index 262fa7d..51ec331 100644 Binary files a/app/migrations/__pycache__/0030_transportcarcassdetail.cpython-312.pyc and b/app/migrations/__pycache__/0030_transportcarcassdetail.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0031_auto_20250921_1447.cpython-312.pyc b/app/migrations/__pycache__/0031_auto_20250921_1447.cpython-312.pyc index f48b274..02bbebf 100644 Binary files a/app/migrations/__pycache__/0031_auto_20250921_1447.cpython-312.pyc and b/app/migrations/__pycache__/0031_auto_20250921_1447.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0032_delete_transportcarcassdetail.cpython-312.pyc b/app/migrations/__pycache__/0032_delete_transportcarcassdetail.cpython-312.pyc index 667865e..03ddff4 100644 Binary files a/app/migrations/__pycache__/0032_delete_transportcarcassdetail.cpython-312.pyc and b/app/migrations/__pycache__/0032_delete_transportcarcassdetail.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0033_transportcarcassdetail.cpython-312.pyc b/app/migrations/__pycache__/0033_transportcarcassdetail.cpython-312.pyc index 13b0136..2521f09 100644 Binary files a/app/migrations/__pycache__/0033_transportcarcassdetail.cpython-312.pyc and b/app/migrations/__pycache__/0033_transportcarcassdetail.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0034_guilds.cpython-312.pyc b/app/migrations/__pycache__/0034_guilds.cpython-312.pyc index f06f7a4..a0c0ad3 100644 Binary files a/app/migrations/__pycache__/0034_guilds.cpython-312.pyc and b/app/migrations/__pycache__/0034_guilds.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0035_guilds_is_steward.cpython-312.pyc b/app/migrations/__pycache__/0035_guilds_is_steward.cpython-312.pyc index f2af498..0a0305a 100644 Binary files a/app/migrations/__pycache__/0035_guilds_is_steward.cpython-312.pyc and b/app/migrations/__pycache__/0035_guilds_is_steward.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0036_driver.cpython-312.pyc b/app/migrations/__pycache__/0036_driver.cpython-312.pyc index 7aeeb52..0448474 100644 Binary files a/app/migrations/__pycache__/0036_driver.cpython-312.pyc and b/app/migrations/__pycache__/0036_driver.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0037_driver_product.cpython-312.pyc b/app/migrations/__pycache__/0037_driver_product.cpython-312.pyc index 03d4cfd..1c34822 100644 Binary files a/app/migrations/__pycache__/0037_driver_product.cpython-312.pyc and b/app/migrations/__pycache__/0037_driver_product.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0038_auto_20250927_0848.cpython-312.pyc b/app/migrations/__pycache__/0038_auto_20250927_0848.cpython-312.pyc index 8b19b96..79e621d 100644 Binary files a/app/migrations/__pycache__/0038_auto_20250927_0848.cpython-312.pyc and b/app/migrations/__pycache__/0038_auto_20250927_0848.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0039_alter_transportcarcassdetail_tracking.cpython-312.pyc b/app/migrations/__pycache__/0039_alter_transportcarcassdetail_tracking.cpython-312.pyc index b026427..334e790 100644 Binary files a/app/migrations/__pycache__/0039_alter_transportcarcassdetail_tracking.cpython-312.pyc and b/app/migrations/__pycache__/0039_alter_transportcarcassdetail_tracking.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0040_transportcarcassdetail_product_date.cpython-312.pyc b/app/migrations/__pycache__/0040_transportcarcassdetail_product_date.cpython-312.pyc index f7444ed..0a82800 100644 Binary files a/app/migrations/__pycache__/0040_transportcarcassdetail_product_date.cpython-312.pyc and b/app/migrations/__pycache__/0040_transportcarcassdetail_product_date.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0041_transportcarcassdetail_has_product_date.cpython-312.pyc b/app/migrations/__pycache__/0041_transportcarcassdetail_has_product_date.cpython-312.pyc index 15aa539..774f202 100644 Binary files a/app/migrations/__pycache__/0041_transportcarcassdetail_has_product_date.cpython-312.pyc and b/app/migrations/__pycache__/0041_transportcarcassdetail_has_product_date.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0042_alter_driver_created_by_alter_driver_modified_by_and_more.cpython-312.pyc b/app/migrations/__pycache__/0042_alter_driver_created_by_alter_driver_modified_by_and_more.cpython-312.pyc index 591592f..e798b99 100644 Binary files a/app/migrations/__pycache__/0042_alter_driver_created_by_alter_driver_modified_by_and_more.cpython-312.pyc and b/app/migrations/__pycache__/0042_alter_driver_created_by_alter_driver_modified_by_and_more.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0043_allproductstransport.cpython-312.pyc b/app/migrations/__pycache__/0043_allproductstransport.cpython-312.pyc new file mode 100644 index 0000000..6098772 Binary files /dev/null and b/app/migrations/__pycache__/0043_allproductstransport.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0044_evacuationdetail.cpython-312.pyc b/app/migrations/__pycache__/0044_evacuationdetail.cpython-312.pyc new file mode 100644 index 0000000..f0f1946 Binary files /dev/null and b/app/migrations/__pycache__/0044_evacuationdetail.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0045_remove_evacuationdetail_broilerflockrequestid_and_more.cpython-312.pyc b/app/migrations/__pycache__/0045_remove_evacuationdetail_broilerflockrequestid_and_more.cpython-312.pyc new file mode 100644 index 0000000..f28900c Binary files /dev/null and b/app/migrations/__pycache__/0045_remove_evacuationdetail_broilerflockrequestid_and_more.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/0046_rasadyarappinfo.cpython-312.pyc b/app/migrations/__pycache__/0046_rasadyarappinfo.cpython-312.pyc new file mode 100644 index 0000000..a040b7c Binary files /dev/null and b/app/migrations/__pycache__/0046_rasadyarappinfo.cpython-312.pyc differ diff --git a/app/migrations/__pycache__/__init__.cpython-312.pyc b/app/migrations/__pycache__/__init__.cpython-312.pyc index e29035b..66a9919 100644 Binary files a/app/migrations/__pycache__/__init__.cpython-312.pyc and b/app/migrations/__pycache__/__init__.cpython-312.pyc differ diff --git a/app/urls.py b/app/urls.py index abd0ebf..d41facc 100644 --- a/app/urls.py +++ b/app/urls.py @@ -11,9 +11,10 @@ from app.views import get_transport_to_kill, add_kill_house, update_hatching, ge dashboard_province_detail_for_map, TransportCarcassDashboardView, GuildsTransportCarcassDashboardView, \ AllProductsTransportDashboardView, AllProductsTransportProductsListView, update_product_date, \ send_transport_carcass_detail_for_rasadyaar, delete_free_bar_from_rasadyaar, fix_number, \ - get_evacuation_detail_by_request_code, get_evacuation_details_by_request_codes, evacuation_report_type_summary, get_all_products_transport_by_code, \ + get_evacuation_detail_by_request_code, get_evacuation_details_by_request_codes, evacuation_report_type_summary, \ + get_all_products_transport_by_code, \ get_all_products_transport_dashboard_by_code, get_all_products_transport_products_by_code, \ - get_all_products_transport_provinces_by_code + get_all_products_transport_provinces_by_code, get_ai_response router = DefaultRouter() @@ -236,6 +237,7 @@ urlpatterns = [ path('get-all-products-transport-products-by-code/', get_all_products_transport_products_by_code), path('get-all-products-transport-provinces-by-code/', get_all_products_transport_provinces_by_code), path('all_products_transport_excel/', all_products_transport_excel), + path('get_ai_response/', get_ai_response), ] diff --git a/app/views.py b/app/views.py index a1797e9..4e29fda 100644 --- a/app/views.py +++ b/app/views.py @@ -26,7 +26,7 @@ from app.filtersets import PoultryFilterSet, PoultryHatchingFilterSet, Transport PoultryInfoFilterSet, HatchingCalculationsFilterSet, HatchingsFilterSet, TransportingDetailFilterSet, \ KillHouseFilterSet, TransportingDetailCustomFilterSet, CustomHatchingsFilterSet, TransportCarcassDetailFilterSet, \ DriverFilterSet, GuildsFilterSet, AllProductsTransportFilterSet -from app.helper import SSLAdapter, get_hatching_permit_code, normalize_persian_arabic_text +from app.helper import SSLAdapter, get_hatching_permit_code, normalize_persian_arabic_text, apply_date_filter from app.models import Poultry, PoultryHatching, TransportingChickenDetail, Hatching, TransportingDetail, KillHouse, \ ApkInfo, TransportCarcassDetail, Guilds, Driver, InquiryCredentials, AllProductsTransport, EvacuationDetail, \ RasadyarAppInfo @@ -987,7 +987,7 @@ class HatchingsCustomViewSet(viewsets.ModelViewSet): if poultry: hatching.poultry = poultry hatching.save() - + allowed_evacuation_fields = { 'PartIdCode', 'RequestId', 'MoReportId', 'ReportType', 'ReportTypeString', 'ReportDate', 'ReportDateShamsi', 'MoReason', 'MoDate', 'MoDateShamsi', @@ -1308,7 +1308,7 @@ class TransportingDashboardViewSet(viewsets.ModelViewSet): date__gte=date1, date__lte=date2, date__isnull=False - + ) except ValueError: pass @@ -1443,31 +1443,31 @@ class TransportingDetailViewSet(viewsets.ModelViewSet): # Query برای AllProductsTransport با product='مرغ زنده -جهت كشتار' query_all_products = AllProductsTransport.objects.filter( - trash=False, + trash=False, product='مرغ زنده -جهت كشتار' ) - + # اعمال فیلترها روی AllProductsTransport if PartIdCode: query_all_products = query_all_products.filter(jihadi_destination=PartIdCode) - + if RequestCode: query_all_products = query_all_products.filter(hatching__RequestCode=RequestCode) - + if date1 and date2: query_all_products = query_all_products.filter( date__gte=date1, date__lte=date2, date__isnull=False - + ) - + if city: query_all_products = query_all_products.filter(destination_city__icontains=city) - + if province: query_all_products = query_all_products.filter(destination_province__icontains=province) - + if search: if search != 'undefined' and search.strip(): transports = transports.filter( @@ -1477,11 +1477,11 @@ class TransportingDetailViewSet(viewsets.ModelViewSet): query_all_products = query_all_products.filter( build_query(AllProductsTransportFilterSet.Meta.fields, search) ) - + # تبدیل به list و ترکیب transports_list = list(transports) all_products_list = list(query_all_products) - + # تبدیل AllProductsTransport به TransportingDetail-like objects برای sort def get_sort_date(obj): if hasattr(obj, 'Date') and obj.Date: @@ -1494,13 +1494,13 @@ class TransportingDetailViewSet(viewsets.ModelViewSet): elif hasattr(obj, 'unloading_date') and obj.unloading_date: return obj.unloading_date return datetime.date.min - + combined_list = [] for obj in transports_list: combined_list.append((get_sort_date(obj), 'transporting', obj)) for obj in all_products_list: combined_list.append((get_sort_date(obj), 'all_products', obj)) - + combined_list.sort(key=lambda x: x[0], reverse=True) sorted_objects = [obj for _, _, obj in combined_list] @@ -1510,7 +1510,7 @@ class TransportingDetailViewSet(viewsets.ModelViewSet): paginator = self.pagination_class() page = paginator.paginate_queryset(sorted_objects, request) - + if page is not None: serialized_data = [] for obj in page: @@ -1667,25 +1667,25 @@ class TotalKillHousesViewSet(viewsets.ModelViewSet): self.pagination_class.page_size = int(page_size) page = self.paginate_queryset(kill_houses) - + items_to_serialize = page if page is not None else kill_houses part_id_codes = list(kill_houses.values_list('PartIdCode', flat=True).distinct()) info_cache = {} - + if part_id_codes: date1 = request.GET.get('date1') or None date2 = request.GET.get('date2') or None - + bars_query = TransportingDetail.objects.filter( - DesPartIdCode__in=part_id_codes, + DesPartIdCode__in=part_id_codes, trash=False ).only('DesPartIdCode', 'GoodAmount', 'Out', 'Date') - + if date1: date1_obj = datetime.datetime.strptime(str(date1), '%Y-%m-%d').date() date2_obj = datetime.datetime.strptime(str(date2), '%Y-%m-%d').date() bars_query = bars_query.filter(Date__date__gte=date1_obj, Date__date__lte=date2_obj) - + bars_aggregations = bars_query.values('DesPartIdCode').annotate( total=Sum('GoodAmount'), input_total=Sum('GoodAmount', filter=Q(Out=False)), @@ -1694,21 +1694,21 @@ class TotalKillHousesViewSet(viewsets.ModelViewSet): output_count=Count('id', filter=Q(Out=True)), total_count=Count('id') ) - + all_products_query = AllProductsTransport.objects.filter( jihadi_destination__in=part_id_codes, trash=False, product='مرغ زنده -جهت كشتار' ).only('jihadi_destination', 'quantity', 'out', 'date', 'unloading_date') - + if date1: all_products_query = all_products_query.filter( date__gte=date1_obj, date__lte=date2_obj, date__isnull=False - + ) - + all_products_aggregations = all_products_query.values('jihadi_destination').annotate( total=Sum('quantity'), input_total=Sum('quantity', filter=Q(out=False)), @@ -1717,28 +1717,28 @@ class TotalKillHousesViewSet(viewsets.ModelViewSet): output_count=Count('id', filter=Q(out=True)), total_count=Count('id') ) - + bars_dict = {item['DesPartIdCode']: item for item in bars_aggregations} all_products_dict = {item['jihadi_destination']: item for item in all_products_aggregations} - + for part_id_code in part_id_codes: bars_data = bars_dict.get(part_id_code, {}) all_products_data = all_products_dict.get(part_id_code, {}) - + total_count = (bars_data.get('total_count') or 0) + (all_products_data.get('total_count') or 0) total_bars_quantity = (bars_data.get('total') or 0) + (all_products_data.get('total') or 0) total_input_bars_quantity = (bars_data.get('input_total') or 0) + (all_products_data.get('input_total') or 0) total_output_bars_quantity = (bars_data.get('output_total') or 0) + (all_products_data.get('output_total') or 0) input_bars_count = (bars_data.get('input_count') or 0) + (all_products_data.get('input_count') or 0) output_bars_count = (bars_data.get('output_count') or 0) + (all_products_data.get('output_count') or 0) - + if total_count > 0: total_input_bars_percent = round((input_bars_count / total_count) * 100, 1) total_output_bars_percent = round((output_bars_count / total_count) * 100, 1) else: total_input_bars_percent = 0 total_output_bars_percent = 0 - + info_cache[part_id_code] = { "bars": total_count, "total_bars_quantity": total_bars_quantity, @@ -2259,7 +2259,7 @@ def dashboard_total_kill_house(request): build_query(filterset_class.Meta.fields, search) ) part_id_codes = list(kill_houses.values_list('PartIdCode', flat=True)) - + if not part_id_codes: return Response({ "killHouseCount": 0, @@ -2274,12 +2274,12 @@ def dashboard_total_kill_house(request): "low_kill_house_name": None, "low_kill_house_amount": None, }) - + # بهینه‌سازی: استفاده از only() برای کاهش داده‌های خوانده شده bars = TransportingDetail.objects.filter(DesPartIdCode__in=part_id_codes, trash=False).only('DesPartIdCode', 'GoodAmount', 'Out', 'Date') - + all_products_transport = AllProductsTransport.objects.filter( - jihadi_destination__in=part_id_codes, + jihadi_destination__in=part_id_codes, trash=False, product='مرغ زنده -جهت كشتار' ).only('jihadi_destination', 'quantity', 'out', 'date', 'unloading_date') @@ -2292,27 +2292,27 @@ def dashboard_total_kill_house(request): date__gte=date1, date__lte=date2, date__isnull=False - + ) # بهینه‌سازی: ترکیب aggregation ها در یک query kill_house_stats_bars = bars.values('DesPartIdCode').annotate( total_amount=Sum('GoodAmount') ) - + kill_house_stats_all_products = all_products_transport.values('jihadi_destination').annotate( total_amount=Sum('quantity') ) - + # بهینه‌سازی: استفاده از dictionary comprehension stats_dict = {stat['DesPartIdCode']: (stat['total_amount'] or 0) for stat in kill_house_stats_bars} - + for stat in kill_house_stats_all_products: part_id = stat['jihadi_destination'] stats_dict[part_id] = stats_dict.get(part_id, 0) + (stat['total_amount'] or 0) - + kill_house_stats = [ - {'DesPartIdCode': k, 'total_amount': v} + {'DesPartIdCode': k, 'total_amount': v} for k, v in sorted(stats_dict.items(), key=lambda x: x[1], reverse=True) ] @@ -2325,10 +2325,10 @@ def dashboard_total_kill_house(request): # بهینه‌سازی: یک query برای هر دو kill house kill_house_part_ids = [top_stat['DesPartIdCode'], low_stat['DesPartIdCode']] kill_houses_dict = {kh.PartIdCode: kh for kh in KillHouse.objects.filter(PartIdCode__in=kill_house_part_ids).only('PartIdCode', 'UnitName')} - + top_kill_house = kill_houses_dict.get(top_stat['DesPartIdCode']) low_kill_house = kill_houses_dict.get(low_stat['DesPartIdCode']) - + if top_kill_house: top_kill_house_info = { "name": top_kill_house.UnitName, @@ -2349,7 +2349,7 @@ def dashboard_total_kill_house(request): output_count=Count('id', filter=Q(Out=True)), total_count=Count('id') ) - + aggregation_all_products = all_products_transport.aggregate( total=Sum('quantity'), input_total=Sum('quantity', filter=Q(out=False)), @@ -2732,7 +2732,7 @@ class RasadyarAppInfoViewSet(viewsets.ModelViewSet): uploaded_file = request.FILES['file'] file_extension = uploaded_file.name.split('.')[-1] if '.' in uploaded_file.name else '' unique_filename = f"rasadyar_app_info_{uuid.uuid4().hex}.{file_extension}" if file_extension else f"rasadyar_app_info_{uuid.uuid4().hex}" - + file_url = upload_to_liara(uploaded_file, unique_filename) instance.file = file_url @@ -2792,17 +2792,17 @@ class TransportCarcassDetailViewSet(viewsets.ModelViewSet): date1 = request.GET.get('date1') code = request.GET.get('code') filters={} - + # Query برای TransportCarcassDetail query_carcass = self.queryset.filter(jihadi_origin=code) - + # Query برای AllProductsTransport با product='گوشت مرغ تازه' query_all_products = AllProductsTransport.objects.filter( - trash=False, + trash=False, product='گوشت مرغ تازه', jihadi_origin=code ) - + if date1: date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() @@ -2821,13 +2821,13 @@ class TransportCarcassDetailViewSet(viewsets.ModelViewSet): ) ) query_all_products = query_all_products.filter( - + date__gte=date1, date__lte=date2, date__isnull=False - + ) - + if search: if search != 'undefined' and search.strip(): query_carcass = query_carcass.filter( @@ -2837,11 +2837,11 @@ class TransportCarcassDetailViewSet(viewsets.ModelViewSet): query_all_products = query_all_products.filter( build_query(AllProductsTransportFilterSet.Meta.fields, search) ) - + # تبدیل به list و ترکیب carcass_list = list(query_carcass) all_products_list = list(query_all_products) - + # تبدیل AllProductsTransport به TransportCarcassDetail-like objects برای sort def get_sort_date(obj): if hasattr(obj, 'product_date') and obj.product_date: @@ -2851,17 +2851,17 @@ class TransportCarcassDetailViewSet(viewsets.ModelViewSet): elif hasattr(obj, 'unloading_date') and obj.unloading_date: return obj.unloading_date return datetime.date.min - + # ایجاد یک list ترکیبی با tuple (date, source_type, obj) combined_list = [] for obj in carcass_list: combined_list.append((get_sort_date(obj), 'carcass', obj)) for obj in all_products_list: combined_list.append((get_sort_date(obj), 'all_products', obj)) - + # sort بر اساس date (از جدید به قدیم) combined_list.sort(key=lambda x: x[0], reverse=True) - + # جدا کردن objects sorted_objects = [obj for _, _, obj in combined_list] @@ -2872,7 +2872,7 @@ class TransportCarcassDetailViewSet(viewsets.ModelViewSet): # Pagination روی list paginator = self.pagination_class() page = paginator.paginate_queryset(sorted_objects, request) - + if page is not None: # Serialize هر object با serializer مناسب serialized_data = [] @@ -3407,12 +3407,12 @@ class TransportCarcassDashboardView(APIView): TrackingStatusDescription__in=("تایید تخلیه",'بارگیری')).only( 'GoodAmount', 'Out') all_products_transport_carcass = AllProductsTransport.objects.filter( - trash=False, + trash=False, product='گوشت مرغ تازه', jihadi_origin__in=kill_house ) all_products_transport = AllProductsTransport.objects.filter( - trash=False, + trash=False, product='مرغ زنده -جهت كشتار', jihadi_destination__in=kill_house ) @@ -3635,21 +3635,21 @@ class TransportCarcassDashboardView(APIView): }) return Response('ok', status=status.HTTP_200_OK) - + def _get_last_update_date_for_dashboard(self, queryset1, queryset2): """تابع helper برای دریافت آخرین تاریخ به‌روزرسانی از دو queryset""" dates = [] - + if queryset1.exists(): first_obj = queryset1.first() if first_obj and hasattr(first_obj, 'modify_date') and first_obj.modify_date: dates.append(first_obj.modify_date) - + if queryset2.exists(): first_obj = queryset2.first() if first_obj and hasattr(first_obj, 'modify_date') and first_obj.modify_date: dates.append(first_obj.modify_date) - + return max(dates) if dates else None @@ -3671,18 +3671,18 @@ class GuildsTransportCarcassViewSet(viewsets.ModelViewSet): code = request.GET.get('code') date1 = request.GET.get('date1') filters={} - + query_carcass = TransportCarcassDetail.objects.filter( jihadi_destination=code, trash=False ) - + query_all_products = AllProductsTransport.objects.filter( - trash=False, + trash=False, product='گوشت مرغ تازه', jihadi_destination=code ) - + if date1: date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() @@ -3702,9 +3702,9 @@ class GuildsTransportCarcassViewSet(viewsets.ModelViewSet): date__gte=date1, date__lte=date2, date__isnull=False - + ) - + if search and search != 'undefined' and search.strip(): query_carcass = query_carcass.filter( build_query(self.filterset_class.Meta.fields, search) @@ -3712,10 +3712,10 @@ class GuildsTransportCarcassViewSet(viewsets.ModelViewSet): query_all_products = query_all_products.filter( build_query(AllProductsTransportFilterSet.Meta.fields, search) ) - + carcass_list = list(query_carcass) all_products_list = list(query_all_products) - + def get_sort_date(obj): if hasattr(obj, 'product_date') and obj.product_date: return obj.product_date @@ -3724,13 +3724,13 @@ class GuildsTransportCarcassViewSet(viewsets.ModelViewSet): elif hasattr(obj, 'unloading_date') and obj.unloading_date: return obj.unloading_date return datetime.date.min - + combined_list = [] for obj in carcass_list: combined_list.append((get_sort_date(obj), 'carcass', obj)) for obj in all_products_list: combined_list.append((get_sort_date(obj), 'all_products', obj)) - + combined_list.sort(key=lambda x: x[0], reverse=True) sorted_objects = [obj for _, _, obj in combined_list] @@ -3740,7 +3740,7 @@ class GuildsTransportCarcassViewSet(viewsets.ModelViewSet): paginator = self.pagination_class() page = paginator.paginate_queryset(sorted_objects, request) - + if page is not None: serialized_data = [] for obj in page: @@ -3791,11 +3791,11 @@ class GuildsTransportCarcassViewSet(viewsets.ModelViewSet): jihadi_destination__in=steward_jihadi_codes ).order_by('-product_date') all_products_transport = AllProductsTransport.objects.filter( - trash=False, + trash=False, product='گوشت مرغ تازه', jihadi_destination__in=steward_jihadi_codes ) - + if date1: date1 = datetime.datetime.strptime(str(date1), '%Y-%m-%d').date() date2 = datetime.datetime.strptime(str(date2), '%Y-%m-%d').date() @@ -3866,7 +3866,7 @@ class GuildsTransportCarcassViewSet(viewsets.ModelViewSet): if st.jihadi_code and st.jihadi_code not in seen_jihadi_codes: seen_jihadi_codes.add(st.jihadi_code) unique_stewards.append(st) - + unique_stewards.sort( key=lambda st: (bars_dict.get(st.jihadi_code, {}) or {}).get('total_ware_house', 0) or 0, reverse=True @@ -3920,7 +3920,7 @@ class GuildsTransportCarcassDashboardView(APIView): product='گوشت مرغ تازه', jihadi_destination__in=steward ) - + if date1: date1 = datetime.datetime.strptime(str(date1), '%Y-%m-%d').date() date2 = datetime.datetime.strptime(str(date2), '%Y-%m-%d').date() @@ -4160,14 +4160,14 @@ def send_transport_carcass_detail_for_rasadyaar(request): quarantine_bars = list(bars.values_list('tracking',flat=True).distinct()) quarantine_buy = list(buy_bars.values_list('TrackingCode',flat=True).distinct()) all_track = quarantine_bars + quarantine_buy - + all_products_carcass = AllProductsTransport.objects.filter( - date__gte=date1, + date__gte=date1, date__lte=date2, trash=False, product='گوشت مرغ تازه' ).exclude(tracking__in=all_track).only('quantity','out','id','jihadi_origin', 'tracking') - + all_products_live = AllProductsTransport.objects.filter( date__gte=date_1_for_buy_bars, date__lte=date_2_for_buy_bars, date__isnull=False, trash=False, @@ -4182,7 +4182,7 @@ def send_transport_carcass_detail_for_rasadyaar(request): output_count=Count('id', filter=Q(out=True)), total_count=Count('id'), ) - + all_products_carcass_summary = all_products_carcass.values('jihadi_origin').annotate( total=Sum('quantity'), input_total=Sum('quantity', filter=Q(out=False)), @@ -4200,7 +4200,7 @@ def send_transport_carcass_detail_for_rasadyaar(request): output_count=Count('id', filter=Q(Out=True)), total_count=Count('id'), ) - + all_products_live_summary = all_products_live.values('jihadi_destination').annotate( total=Sum('quantity'), input_total=Sum('quantity', filter=Q(out=False)), @@ -4267,7 +4267,7 @@ def send_transport_carcass_detail_for_rasadyaar(request): buy_dict[key]['input_count'] += row['input_count'] or 0 buy_dict[key]['output_count'] += row['output_count'] or 0 buy_dict[key]['total_count'] += row['total_count'] or 0 - + for row in all_products_live_summary: key = row['jihadi_destination'] if key: @@ -4353,16 +4353,16 @@ def get_evacuation_details_by_request_codes(request): result = {} hatchings = Hatching.objects.filter(RequestCode__in=request_codes, trash=False) - + for hatching in hatchings: evacuations = EvacuationDetail.objects.filter(hatching=hatching, trash=False).order_by('-create_date') serializer = EvacuationDetailSerializer(evacuations, many=True) result[hatching.RequestCode] = serializer.data - + for code in request_codes: if code not in result: result[code] = [] - + return Response(result, status=status.HTTP_200_OK) @@ -4393,23 +4393,23 @@ class EvacuationDetailViewSet(viewsets.ModelViewSet): def create(self, request, *args, **kwargs): data_list = request.data if isinstance(request.data, list) else [request.data] - + total_created = 0 total_updated = 0 - + for item_data in data_list: evacuation_details = item_data.get('EvacuationDetail', []) if not evacuation_details or len(evacuation_details) == 0: continue - + request_code = item_data.get('RequestCode') if not request_code: continue - + hatching = Hatching.objects.filter(RequestCode=request_code, trash=False).first() if not hatching: continue - + for evacuation_data in evacuation_details: clean_data = evacuation_data.copy() external_id = clean_data.pop('Id', None) @@ -4421,7 +4421,7 @@ class EvacuationDetailViewSet(viewsets.ModelViewSet): ExternalId=external_id, trash=False ).first() - + if evacuation: for key, value in clean_data.items(): setattr(evacuation, key, value) @@ -4432,7 +4432,7 @@ class EvacuationDetailViewSet(viewsets.ModelViewSet): clean_data['hatching'] = hatching EvacuationDetail.objects.create(**clean_data) total_created += 1 - + return Response({ "result": "با موفقیت ثبت شد", "created": total_created, @@ -4441,14 +4441,14 @@ class EvacuationDetailViewSet(viewsets.ModelViewSet): def list(self, request, *args, **kwargs): evacuations = self.filter_queryset(self.get_queryset()) - + search = request.GET.get('search') if search: if search != 'undefined' and search.strip(): evacuations = evacuations.filter( build_query(['TrackingCode', 'SourceUnitName', 'DesUnitName'], search) ) - + page_size = request.query_params.get('page_size', None) if page_size: self.pagination_class.page_size = int(page_size) @@ -4557,7 +4557,7 @@ class AllProductsTransportViewSet(viewsets.ModelViewSet): location_cache = {} context = self.get_serializer_context() context['location_cache'] = location_cache - + if page is not None: serializer = self.get_serializer(page, many=True, context=context) return self.get_paginated_response(serializer.data) @@ -4635,7 +4635,7 @@ class AllProductsTransportViewSet(viewsets.ModelViewSet): continue row_data = dict(zip(headers, row)) - + tracking_val = row_data.get("کد رهگیری") or row_data.get("رهگیری") province_name = row_data.get("شهرستان مقصد") or row_data.get("شهرستان مقصد") jihadi_origin_code = row_data.get("ش جهادی مبدا") or row_data.get("ش جهادی مبدا") @@ -4654,7 +4654,7 @@ class AllProductsTransportViewSet(viewsets.ModelViewSet): for col_name, model_field in field_map.items(): if col_name in row_data: value = row_data[col_name] - + if model_field in ["date", "unloading_date"] and value: try: if isinstance(value, str): @@ -4669,7 +4669,7 @@ class AllProductsTransportViewSet(viewsets.ModelViewSet): value = convert_to_miladi(value.year, value.month, value.day) except (ValueError, AttributeError, IndexError): value = None - + if model_field == "quantity" and value: try: if isinstance(value, str): @@ -4678,7 +4678,7 @@ class AllProductsTransportViewSet(viewsets.ModelViewSet): value = float(value) except (ValueError, TypeError): value = None - + if model_field in ["gross_weight", "tare_weight", "net_weight"] and value: try: if isinstance(value, str): @@ -4687,7 +4687,7 @@ class AllProductsTransportViewSet(viewsets.ModelViewSet): value = float(value) except (ValueError, TypeError): value = None - + record_data[model_field] = value hatching_obj = None @@ -4718,12 +4718,12 @@ class AllProductsTransportViewSet(viewsets.ModelViewSet): if hatching_obj: new_record.hatching = hatching_obj new_record.save() - + if new_record.destination_province and new_record.origin_province: if new_record.destination_province != new_record.origin_province: new_record.out = True new_record.save() - + created_count += 1 return Response({ @@ -4978,7 +4978,7 @@ def _convert_transporting_detail_to_unified(obj): 'RequestCode': obj.hatching.RequestCode, 'PedigreeName': obj.hatching.PedigreeName, } - + return { 'id': obj.id, 'key': str(obj.key), @@ -5075,7 +5075,7 @@ def _convert_all_products_to_unified(obj): 'RequestCode': obj.hatching.RequestCode, 'PedigreeName': obj.hatching.PedigreeName, } - + return { 'id': obj.id, 'key': str(obj.key), @@ -5120,24 +5120,24 @@ def get_all_products_transport_by_code(request): code = request.GET.get('code') if not code: return Response( - {'detail': 'کد الزامی است'}, + {'detail': 'کد الزامی است'}, status=status.HTTP_400_BAD_REQUEST ) - + transport_type = request.GET.get('type') if transport_type not in ['in', 'out']: return Response( - {'detail': 'نوع باید in یا out باشد'}, + {'detail': 'نوع باید in یا out باشد'}, status=status.HTTP_400_BAD_REQUEST ) - + from_source = request.GET.get('from') if from_source and from_source not in ['Poultry', 'KillHouse']: return Response( - {'detail': 'from باید Poultry یا KillHouse باشد'}, + {'detail': 'from باید Poultry یا KillHouse باشد'}, status=status.HTTP_400_BAD_REQUEST ) - + date1 = request.GET.get('date1') date2 = request.GET.get('date2') start_date = None @@ -5148,14 +5148,14 @@ def get_all_products_transport_by_code(request): end_date = datetime.datetime.strptime(str(date2), '%Y-%m-%d') except ValueError: pass - + province = request.GET.get('province') product_type = request.GET.get('product') search = request.GET.get('search') - + unified_results = [] seen_tracking_codes = set() - + def add_if_not_duplicate(item): tracking = item.get('tracking') if tracking and tracking in seen_tracking_codes: @@ -5164,7 +5164,7 @@ def get_all_products_transport_by_code(request): seen_tracking_codes.add(tracking) unified_results.append(item) return True - + if from_source == 'Poultry': if transport_type == 'out': all_products = AllProductsTransport.objects.filter( @@ -5177,10 +5177,10 @@ def get_all_products_transport_by_code(request): all_products = all_products.filter(destination_province=province) if product_type and product_type != 'undefined': all_products = all_products.filter(product=product_type) - + for obj in all_products: add_if_not_duplicate(_convert_all_products_to_unified(obj)) - + transport_details = TransportingDetail.objects.filter( trash=False, hatching__poultry__PartIdCode=code, @@ -5190,7 +5190,7 @@ def get_all_products_transport_by_code(request): transport_details = transport_details.filter(Date__gte=start_date, Date__lte=end_date) if province and province != 'undefined': transport_details = transport_details.filter(Province=province) - + for obj in transport_details: add_if_not_duplicate(_convert_transporting_detail_to_unified(obj)) else: @@ -5204,10 +5204,10 @@ def get_all_products_transport_by_code(request): all_products = all_products.filter(origin_province=province) if product_type and product_type != 'undefined': all_products = all_products.filter(product=product_type) - + for obj in all_products: add_if_not_duplicate(_convert_all_products_to_unified(obj)) - + elif from_source == 'KillHouse': if transport_type == 'out': carcass_details = TransportCarcassDetail.objects.filter( @@ -5220,7 +5220,7 @@ def get_all_products_transport_by_code(request): carcass_details = carcass_details.filter(destination_province=province) if product_type and product_type != 'undefined': carcass_details = carcass_details.filter(product=product_type) - + for obj in carcass_details: add_if_not_duplicate(_convert_transport_carcass_to_unified(obj)) else: @@ -5233,10 +5233,10 @@ def get_all_products_transport_by_code(request): transport_details = transport_details.filter(Date__gte=start_date, Date__lte=end_date) if province and province != 'undefined': transport_details = transport_details.filter(hatching__ProvinceName=province) - + for obj in transport_details: add_if_not_duplicate(_convert_transporting_detail_to_unified(obj)) - + else: if transport_type == 'out': bars = AllProductsTransport.objects.filter( @@ -5248,7 +5248,7 @@ def get_all_products_transport_by_code(request): trash=False, jihadi_destination=code ) - + if start_date and end_date: bars = bars.filter(date__gte=start_date, date__lte=end_date) if province and province != 'undefined': @@ -5258,10 +5258,10 @@ def get_all_products_transport_by_code(request): bars = bars.filter(origin_province=province) if product_type and product_type != 'undefined': bars = bars.filter(product=product_type) - + for obj in bars: add_if_not_duplicate(_convert_all_products_to_unified(obj)) - + if search and search != 'undefined' and search.strip(): search_lower = search.lower() unified_results = [ @@ -5273,19 +5273,19 @@ def get_all_products_transport_by_code(request): (r.get('driver_name') and search_lower in str(r['driver_name']).lower()) or (r.get('owner') and search_lower in str(r['owner']).lower()) ] - + unified_results.sort(key=lambda x: x.get('date') or datetime.date.min, reverse=True) - + paginator = CustomPagination() page_size = request.query_params.get('page_size', None) if page_size: paginator.page_size = int(page_size) - + page_number = int(request.query_params.get('page', 1)) start_index = (page_number - 1) * paginator.page_size end_index = start_index + paginator.page_size paginated_results = unified_results[start_index:end_index] - + return Response({ 'count': len(unified_results), 'next': f"?page={page_number + 1}" if end_index < len(unified_results) else None, @@ -5301,24 +5301,24 @@ def get_all_products_transport_products_by_code(request): code = request.GET.get('code') if not code: return Response( - {'detail': 'کد الزامی است'}, + {'detail': 'کد الزامی است'}, status=status.HTTP_400_BAD_REQUEST ) - + transport_type = request.GET.get('type') if transport_type not in ['in', 'out']: return Response( - {'detail': 'نوع باید in یا out باشد'}, + {'detail': 'نوع باید in یا out باشد'}, status=status.HTTP_400_BAD_REQUEST ) - + from_source = request.GET.get('from') if from_source and from_source not in ['Poultry', 'KillHouse']: return Response( - {'detail': 'from باید Poultry یا KillHouse باشد'}, + {'detail': 'from باید Poultry یا KillHouse باشد'}, status=status.HTTP_400_BAD_REQUEST ) - + date1 = request.GET.get('date1') date2 = request.GET.get('date2') start_date = None @@ -5329,13 +5329,13 @@ def get_all_products_transport_products_by_code(request): end_date = datetime.datetime.strptime(str(date2), '%Y-%m-%d') except ValueError: pass - + province = request.GET.get('province') product_type = request.GET.get('product') search = request.GET.get('search') - - products_set = set() - + + products_set = set() + if from_source == 'Poultry': if transport_type == 'out': all_products = AllProductsTransport.objects.filter( @@ -5348,14 +5348,14 @@ def get_all_products_transport_products_by_code(request): all_products = all_products.filter(destination_province=province) if product_type and product_type != 'undefined': all_products = all_products.filter(product=product_type) - + products_set.update( all_products.filter(product__isnull=False) .exclude(product='') .values_list('product', flat=True) .distinct() ) - + transport_details = TransportingDetail.objects.filter( trash=False, hatching__poultry__PartIdCode=code, @@ -5365,7 +5365,7 @@ def get_all_products_transport_products_by_code(request): transport_details = transport_details.filter(Date__gte=start_date, Date__lte=end_date) if province and province != 'undefined': transport_details = transport_details.filter(Province=province) - + products_set.update( transport_details.filter(GoodName__isnull=False) .exclude(GoodName='') @@ -5383,14 +5383,14 @@ def get_all_products_transport_products_by_code(request): all_products = all_products.filter(origin_province=province) if product_type and product_type != 'undefined': all_products = all_products.filter(product=product_type) - + products_set.update( all_products.filter(product__isnull=False) .exclude(product='') .values_list('product', flat=True) .distinct() ) - + elif from_source == 'KillHouse': if transport_type == 'out': carcass_details = TransportCarcassDetail.objects.filter( @@ -5403,7 +5403,7 @@ def get_all_products_transport_products_by_code(request): carcass_details = carcass_details.filter(destination_province=province) if product_type and product_type != 'undefined': carcass_details = carcass_details.filter(product=product_type) - + products_set.update( carcass_details.filter(product__isnull=False) .exclude(product='') @@ -5420,14 +5420,14 @@ def get_all_products_transport_products_by_code(request): transport_details = transport_details.filter(Date__gte=start_date, Date__lte=end_date) if province and province != 'undefined': transport_details = transport_details.filter(hatching__ProvinceName=province) - + products_set.update( transport_details.filter(GoodName__isnull=False) .exclude(GoodName='') .values_list('GoodName', flat=True) .distinct() ) - + else: if transport_type == 'out': bars = AllProductsTransport.objects.filter( @@ -5439,7 +5439,7 @@ def get_all_products_transport_products_by_code(request): trash=False, jihadi_destination=code ) - + if start_date and end_date: bars = bars.filter(date__gte=start_date, date__lte=end_date) if province and province != 'undefined': @@ -5456,16 +5456,16 @@ def get_all_products_transport_products_by_code(request): .values_list('product', flat=True) .distinct() ) - + if search and search != 'undefined' and search.strip(): search_lower = search.lower() products_set = { p for p in products_set if p and search_lower in str(p).lower() } - + products = sorted([p for p in products_set if p], key=str) - + return Response({ "products": products }, status=status.HTTP_200_OK) @@ -5478,24 +5478,24 @@ def get_all_products_transport_provinces_by_code(request): code = request.GET.get('code') if not code: return Response( - {'detail': 'کد الزامی است'}, + {'detail': 'کد الزامی است'}, status=status.HTTP_400_BAD_REQUEST ) - + transport_type = request.GET.get('type') if transport_type not in ['in', 'out']: return Response( - {'detail': 'نوع باید in یا out باشد'}, + {'detail': 'نوع باید in یا out باشد'}, status=status.HTTP_400_BAD_REQUEST ) - + from_source = request.GET.get('from') if from_source and from_source not in ['Poultry', 'KillHouse']: return Response( - {'detail': 'from باید Poultry یا KillHouse باشد'}, + {'detail': 'from باید Poultry یا KillHouse باشد'}, status=status.HTTP_400_BAD_REQUEST ) - + date1 = request.GET.get('date1') date2 = request.GET.get('date2') start_date = None @@ -5506,12 +5506,12 @@ def get_all_products_transport_provinces_by_code(request): end_date = datetime.datetime.strptime(str(date2), '%Y-%m-%d') except ValueError: pass - + province = request.GET.get('province') product_type = request.GET.get('product') search = request.GET.get('search') - provinces_set = set() - + provinces_set = set() + if from_source == 'Poultry': if transport_type == 'out': all_products = AllProductsTransport.objects.filter( @@ -5524,14 +5524,14 @@ def get_all_products_transport_provinces_by_code(request): all_products = all_products.filter(destination_province=province) if product_type and product_type != 'undefined': all_products = all_products.filter(product=product_type) - + provinces_set.update( all_products.filter(destination_province__isnull=False) .exclude(destination_province='') .values_list('destination_province', flat=True) .distinct() ) - + transport_details = TransportingDetail.objects.filter( trash=False, hatching__poultry__PartIdCode=code, @@ -5541,7 +5541,7 @@ def get_all_products_transport_provinces_by_code(request): transport_details = transport_details.filter(Date__gte=start_date, Date__lte=end_date) if province and province != 'undefined': transport_details = transport_details.filter(Province=province) - + provinces_set.update( transport_details.filter(Province__isnull=False) .exclude(Province='') @@ -5559,14 +5559,14 @@ def get_all_products_transport_provinces_by_code(request): all_products = all_products.filter(origin_province=province) if product_type and product_type != 'undefined': all_products = all_products.filter(product=product_type) - + provinces_set.update( all_products.filter(origin_province__isnull=False) .exclude(origin_province='') .values_list('origin_province', flat=True) .distinct() ) - + elif from_source == 'KillHouse': if transport_type == 'out': carcass_details = TransportCarcassDetail.objects.filter( @@ -5579,7 +5579,7 @@ def get_all_products_transport_provinces_by_code(request): carcass_details = carcass_details.filter(destination_province=province) if product_type and product_type != 'undefined': carcass_details = carcass_details.filter(product=product_type) - + provinces_set.update( carcass_details.filter(destination_province__isnull=False) .exclude(destination_province='') @@ -5596,14 +5596,14 @@ def get_all_products_transport_provinces_by_code(request): transport_details = transport_details.filter(Date__gte=start_date, Date__lte=end_date) if province and province != 'undefined': transport_details = transport_details.filter(hatching__ProvinceName=province) - + provinces_set.update( transport_details.filter(hatching__ProvinceName__isnull=False) .exclude(hatching__ProvinceName='') .values_list('hatching__ProvinceName', flat=True) .distinct() ) - + else: if transport_type == 'out': bars = AllProductsTransport.objects.filter( @@ -5615,7 +5615,7 @@ def get_all_products_transport_provinces_by_code(request): trash=False, jihadi_destination=code ) - + if start_date and end_date: bars = bars.filter(date__gte=start_date, date__lte=end_date) if province and province != 'undefined': @@ -5625,7 +5625,7 @@ def get_all_products_transport_provinces_by_code(request): bars = bars.filter(origin_province=province) if product_type and product_type != 'undefined': bars = bars.filter(product=product_type) - + if transport_type == 'out': provinces_set.update( bars.filter(destination_province__isnull=False) @@ -5640,16 +5640,16 @@ def get_all_products_transport_provinces_by_code(request): .values_list('origin_province', flat=True) .distinct() ) - + if search and search != 'undefined' and search.strip(): search_lower = search.lower() provinces_set = { p for p in provinces_set if p and search_lower in str(p).lower() } - + provinces = sorted([p for p in provinces_set if p], key=str) - + return Response({ "provinces": provinces }, status=status.HTTP_200_OK) @@ -5662,24 +5662,24 @@ def get_all_products_transport_dashboard_by_code(request): code = request.GET.get('code') if not code: return Response( - {'detail': 'کد الزامی است'}, + {'detail': 'کد الزامی است'}, status=status.HTTP_400_BAD_REQUEST ) - + transport_type = request.GET.get('type') if transport_type not in ['in', 'out']: return Response( - {'detail': 'نوع باید in یا out باشد'}, + {'detail': 'نوع باید in یا out باشد'}, status=status.HTTP_400_BAD_REQUEST ) - + from_source = request.GET.get('from') if from_source and from_source not in ['Poultry', 'KillHouse']: return Response( - {'detail': 'from باید Poultry یا KillHouse باشد'}, + {'detail': 'from باید Poultry یا KillHouse باشد'}, status=status.HTTP_400_BAD_REQUEST ) - + date1 = request.GET.get('date1') date2 = request.GET.get('date2') start_date = None @@ -5690,11 +5690,11 @@ def get_all_products_transport_dashboard_by_code(request): end_date = datetime.datetime.strptime(str(date2), '%Y-%m-%d') except ValueError: pass - + province = request.GET.get('province') product_type = request.GET.get('product') search = request.GET.get('search') - + total_count = 0 total_quantity = 0 input_quantity = 0 @@ -5702,7 +5702,7 @@ def get_all_products_transport_dashboard_by_code(request): input_count = 0 output_count = 0 last_update = None - + if from_source == 'Poultry': if transport_type == 'out': all_products = AllProductsTransport.objects.filter( @@ -5715,7 +5715,7 @@ def get_all_products_transport_dashboard_by_code(request): all_products = all_products.filter(destination_province=province) if product_type and product_type != 'undefined': all_products = all_products.filter(product=product_type) - + agg = all_products.aggregate( total=Sum('quantity'), input_total=Sum('quantity', filter=Q(out=False)), @@ -5733,7 +5733,7 @@ def get_all_products_transport_dashboard_by_code(request): output_count += agg['output_cnt'] or 0 if agg['last_mod'] and (not last_update or agg['last_mod'] > last_update): last_update = agg['last_mod'] - + transport_details = TransportingDetail.objects.filter( trash=False, hatching__poultry__PartIdCode=code, @@ -5743,7 +5743,7 @@ def get_all_products_transport_dashboard_by_code(request): transport_details = transport_details.filter(Date__gte=start_date, Date__lte=end_date) if province and province != 'undefined': transport_details = transport_details.filter(Province=province) - + agg = transport_details.aggregate( total=Sum('GoodAmount'), input_total=Sum('GoodAmount', filter=Q(Out=False)), @@ -5772,7 +5772,7 @@ def get_all_products_transport_dashboard_by_code(request): all_products = all_products.filter(origin_province=province) if product_type and product_type != 'undefined': all_products = all_products.filter(product=product_type) - + agg = all_products.aggregate( total=Sum('quantity'), input_total=Sum('quantity', filter=Q(out=False)), @@ -5790,7 +5790,7 @@ def get_all_products_transport_dashboard_by_code(request): output_count += agg['output_cnt'] or 0 if agg['last_mod'] and (not last_update or agg['last_mod'] > last_update): last_update = agg['last_mod'] - + elif from_source == 'KillHouse': if transport_type == 'out': carcass_details = TransportCarcassDetail.objects.filter( @@ -5803,7 +5803,7 @@ def get_all_products_transport_dashboard_by_code(request): carcass_details = carcass_details.filter(destination_province=province) if product_type and product_type != 'undefined': carcass_details = carcass_details.filter(product=product_type) - + agg = carcass_details.aggregate( total=Sum('quantity'), input_total=Sum('quantity', filter=Q(out=False)), @@ -5831,7 +5831,7 @@ def get_all_products_transport_dashboard_by_code(request): transport_details = transport_details.filter(Date__gte=start_date, Date__lte=end_date) if province and province != 'undefined': transport_details = transport_details.filter(hatching__ProvinceName=province) - + agg = transport_details.aggregate( total=Sum('GoodAmount'), input_total=Sum('GoodAmount', filter=Q(Out=False)), @@ -5849,7 +5849,7 @@ def get_all_products_transport_dashboard_by_code(request): output_count += agg['output_cnt'] or 0 if agg['last_mod'] and (not last_update or agg['last_mod'] > last_update): last_update = agg['last_mod'] - + else: if transport_type == 'out': all_bars = AllProductsTransport.objects.filter( @@ -5861,7 +5861,7 @@ def get_all_products_transport_dashboard_by_code(request): trash=False, jihadi_destination=code ) - + if start_date and end_date: all_bars = all_bars.filter(date__gte=start_date, date__lte=end_date) if province and province != 'undefined': @@ -5871,12 +5871,12 @@ def get_all_products_transport_dashboard_by_code(request): all_bars = all_bars.filter(origin_province=province) if product_type and product_type != 'undefined': all_bars = all_bars.filter(product=product_type) - + if search and search != 'undefined' and search.strip(): all_bars = all_bars.filter( build_query(AllProductsTransportFilterSet.Meta.fields, search) ) - + aggregation = all_bars.aggregate( total=Sum('quantity'), input_total=Sum('quantity', filter=Q(out=False)), @@ -5886,7 +5886,7 @@ def get_all_products_transport_dashboard_by_code(request): total_count=Count('id'), last_mod=Max('modify_date'), ) - + total_count = aggregation['total_count'] or 0 total_quantity = aggregation['total'] or 0 input_quantity = aggregation['input_total'] or 0 @@ -5894,14 +5894,14 @@ def get_all_products_transport_dashboard_by_code(request): input_count = aggregation['input_count'] or 0 output_count = aggregation['output_count'] or 0 last_update = aggregation['last_mod'] - + if total_count > 0 and (input_quantity + output_quantity) > 0: input_percent = round((input_quantity / (input_quantity + output_quantity)) * 100, 1) output_percent = round((output_quantity / (input_quantity + output_quantity)) * 100, 1) else: input_percent = 0 output_percent = 0 - + return Response({ "bars": int(total_count), "input_bars": int(input_count), @@ -5915,3 +5915,56 @@ def get_all_products_transport_dashboard_by_code(request): "total_output_bars_percent": output_percent, "total_output_bars_wight": int(output_quantity), }, status=status.HTTP_200_OK) + + + + + +@api_view(['POST']) +@permission_classes([AllowAny]) +@csrf_exempt +def get_ai_response(request): + result_data = {} + models_info = request.data.get('models_info') + + for model_info in models_info: + model_name = model_info.get("model") + filters = model_info.get("filters", {}) + aggregations = model_info.get("aggregations") or [] + fields_to_return = model_info.get("fields_to_return") or [] + date_filter = model_info.get("date_filter") + + if model_name == "Hatching": + queryset = Hatching.objects.filter(**filters) + + elif model_name == "Poultry": + queryset = Poultry.objects.filter(**filters) + + else: + continue + + queryset = apply_date_filter(queryset, date_filter) + + model_result = {} + + if "count" in aggregations: + model_result["count"] = queryset.count() + + if "sum" in aggregations: + model_result["sum"] = ( + queryset.aggregate(total=Sum("ChickCountSum"))["total"] or 0 + ) + + if fields_to_return: + descriptive_data = queryset.values(*fields_to_return).first() + if descriptive_data: + model_result.update(descriptive_data) + + result_data[model_name] = model_result + + return Response( + { + "data": result_data + }, + status=status.HTTP_200_OK + ) diff --git a/authentication/__pycache__/__init__.cpython-312.pyc b/authentication/__pycache__/__init__.cpython-312.pyc index 944ecb1..2adbf58 100644 Binary files a/authentication/__pycache__/__init__.cpython-312.pyc and b/authentication/__pycache__/__init__.cpython-312.pyc differ diff --git a/authentication/__pycache__/admin.cpython-312.pyc b/authentication/__pycache__/admin.cpython-312.pyc index 4d6d9ee..22ffd4d 100644 Binary files a/authentication/__pycache__/admin.cpython-312.pyc and b/authentication/__pycache__/admin.cpython-312.pyc differ diff --git a/authentication/__pycache__/apps.cpython-312.pyc b/authentication/__pycache__/apps.cpython-312.pyc index 2dd6a1c..a54dc8f 100644 Binary files a/authentication/__pycache__/apps.cpython-312.pyc and b/authentication/__pycache__/apps.cpython-312.pyc differ diff --git a/authentication/__pycache__/models.cpython-312.pyc b/authentication/__pycache__/models.cpython-312.pyc index be90410..65846a2 100644 Binary files a/authentication/__pycache__/models.cpython-312.pyc and b/authentication/__pycache__/models.cpython-312.pyc differ diff --git a/authentication/__pycache__/serializers.cpython-312.pyc b/authentication/__pycache__/serializers.cpython-312.pyc index b84f5aa..630a9b0 100644 Binary files a/authentication/__pycache__/serializers.cpython-312.pyc and b/authentication/__pycache__/serializers.cpython-312.pyc differ diff --git a/authentication/__pycache__/urls.cpython-312.pyc b/authentication/__pycache__/urls.cpython-312.pyc index 1c74aa0..d09345c 100644 Binary files a/authentication/__pycache__/urls.cpython-312.pyc and b/authentication/__pycache__/urls.cpython-312.pyc differ diff --git a/authentication/__pycache__/views.cpython-312.pyc b/authentication/__pycache__/views.cpython-312.pyc index 515b16e..9669602 100644 Binary files a/authentication/__pycache__/views.cpython-312.pyc and b/authentication/__pycache__/views.cpython-312.pyc differ diff --git a/authentication/migrations/__pycache__/0001_initial.cpython-312.pyc b/authentication/migrations/__pycache__/0001_initial.cpython-312.pyc index 98b6bfa..9f578ab 100644 Binary files a/authentication/migrations/__pycache__/0001_initial.cpython-312.pyc and b/authentication/migrations/__pycache__/0001_initial.cpython-312.pyc differ diff --git a/authentication/migrations/__pycache__/0002_city_lat_city_lng_province_lat_province_lng.cpython-312.pyc b/authentication/migrations/__pycache__/0002_city_lat_city_lng_province_lat_province_lng.cpython-312.pyc index a43e432..db50bf7 100644 Binary files a/authentication/migrations/__pycache__/0002_city_lat_city_lng_province_lat_province_lng.cpython-312.pyc and b/authentication/migrations/__pycache__/0002_city_lat_city_lng_province_lat_province_lng.cpython-312.pyc differ diff --git a/authentication/migrations/__pycache__/0003_auto_20250809_1248.cpython-312.pyc b/authentication/migrations/__pycache__/0003_auto_20250809_1248.cpython-312.pyc index c80288b..34ffaee 100644 Binary files a/authentication/migrations/__pycache__/0003_auto_20250809_1248.cpython-312.pyc and b/authentication/migrations/__pycache__/0003_auto_20250809_1248.cpython-312.pyc differ diff --git a/authentication/migrations/__pycache__/0004_province_tel_prefix.cpython-312.pyc b/authentication/migrations/__pycache__/0004_province_tel_prefix.cpython-312.pyc index 824ad9a..9f2637c 100644 Binary files a/authentication/migrations/__pycache__/0004_province_tel_prefix.cpython-312.pyc and b/authentication/migrations/__pycache__/0004_province_tel_prefix.cpython-312.pyc differ diff --git a/authentication/migrations/__pycache__/__init__.cpython-312.pyc b/authentication/migrations/__pycache__/__init__.cpython-312.pyc index 7149289..86c899c 100644 Binary files a/authentication/migrations/__pycache__/__init__.cpython-312.pyc and b/authentication/migrations/__pycache__/__init__.cpython-312.pyc differ